├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── boghma ├── c4d │ └── c4d_interact.pyp ├── dialogs │ ├── custom_confirm_dialog.gd │ └── file_dialog.gd ├── finite_state_machine │ ├── base_state.gd │ └── base_state_machine.gd ├── model │ ├── base_hierarchy.gd │ └── uniform_data.gd ├── mvc │ ├── action_message.gd │ ├── base_item.gd │ ├── base_message.gd │ ├── controller.gd │ ├── item_factory.gd │ └── update_message.gd ├── scripts │ ├── custom_iterator.gd │ ├── factory.gd │ ├── free_parent_when_start.gd │ ├── funfile.gd │ ├── json_helper.gd │ ├── result_helper.gd │ ├── scene_manager.gd │ ├── structure.gd │ ├── thread_helper.gd │ └── uuid.gd └── utils │ ├── http_request_helper.gd │ └── spring_function.gd ├── components ├── cell_grid.gd ├── custom_window_bar │ ├── cusBBE6.tmp │ ├── custom_window_bar.gd │ ├── custom_window_bar.tscn │ ├── example │ │ └── cwb_application_example.tscn │ ├── window_drag_component.gd │ ├── window_resize_component.gd │ └── window_state_component.gd ├── dashline_stylebox │ └── dashline_stylebox.gd ├── draggable_card_component │ ├── card │ │ ├── base_draggable_card.gd │ │ ├── base_draggable_card.tscn │ │ ├── place_holder_panel.gd │ │ ├── place_holder_panel.tscn │ │ └── shadow_panel.tscn │ ├── draggable_card_component.gd │ ├── draggable_card_component.tscn │ └── example │ │ ├── custom_card.gd │ │ ├── custom_card.tscn │ │ ├── draggable_card_example.gd │ │ └── draggable_card_example.tscn └── mograph_component │ ├── effector │ ├── mograph_base_effector.gd │ ├── mograph_delay_effector.gd │ ├── mograph_plain_effector.gd │ └── mograph_target_effector.gd │ ├── example │ ├── mograph_effector_example.tscn │ ├── mograph_grid_example.tscn │ ├── mograph_linear_example.tscn │ └── mograph_radial_example.tscn │ ├── field │ ├── mograph_base_field.gd │ ├── mograph_circle_field.gd │ └── mograph_linear_field.gd │ ├── mograph_container │ ├── mograph_base_container.gd │ ├── mograph_grid_container.gd │ ├── mograph_linear_container.gd │ └── mograph_radial_container.gd │ ├── test │ └── control_1.tscn │ └── tool │ └── container_transform_viewer.gd ├── example ├── custom_iterator │ ├── custom_iterator.gd │ └── custom_iterator.tscn ├── factory │ ├── example_factory.gd │ └── example_factory.tscn └── result_helper │ ├── example_result_helper.gd │ └── example_result_helper.tscn ├── globals └── debug │ ├── debug_panel.gd │ └── debug_panel.tscn ├── icon.svg ├── icon.svg.import ├── project.godot ├── resource ├── clear icon cache on window.bat ├── fonts │ ├── NotosansSC │ │ ├── NotoSansCJK-Black-7.otf │ │ ├── NotoSansCJK-Black-7.otf.import │ │ ├── NotoSansCJK-Bold-6.otf │ │ ├── NotoSansCJK-Bold-6.otf.import │ │ ├── NotoSansCJK-DemiLight-4.otf │ │ ├── NotoSansCJK-DemiLight-4.otf.import │ │ ├── NotoSansCJK-Light-3.otf │ │ ├── NotoSansCJK-Light-3.otf.import │ │ ├── NotoSansCJK-Medium-5.otf │ │ ├── NotoSansCJK-Medium-5.otf.import │ │ ├── NotoSansCJK-Regular-1.otf │ │ ├── NotoSansCJK-Regular-1.otf.import │ │ ├── NotoSansCJK-Thin-2.otf │ │ └── NotoSansCJK-Thin-2.otf.import │ └── inter │ │ ├── Inter-VariableFont_slnt,wght.ttf │ │ ├── Inter-VariableFont_slnt,wght.ttf.import │ │ └── static │ │ ├── Inter-Black.ttf │ │ ├── Inter-Black.ttf.import │ │ ├── Inter-Bold.ttf │ │ ├── Inter-Bold.ttf.import │ │ ├── Inter-ExtraBold.ttf │ │ ├── Inter-ExtraBold.ttf.import │ │ ├── Inter-ExtraLight.ttf │ │ ├── Inter-ExtraLight.ttf.import │ │ ├── Inter-Light.ttf │ │ ├── Inter-Light.ttf.import │ │ ├── Inter-Medium.ttf │ │ ├── Inter-Medium.ttf.import │ │ ├── Inter-Regular.ttf │ │ ├── Inter-Regular.ttf.import │ │ ├── Inter-SemiBold.ttf │ │ ├── Inter-SemiBold.ttf.import │ │ ├── Inter-Thin.ttf │ │ └── Inter-Thin.ttf.import ├── icons │ ├── Boghma.png │ ├── Boghma.png.import │ ├── drag.png │ ├── drag.png.import │ ├── godot.png │ └── godot.png.import └── shader │ └── ms_fill.tres └── tips.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | # Normalize EOL for all files that Git considers text files. 2 | * text=auto eol=lf 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Godot 4+ specific ignores 2 | .godot/ 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 JACKADUX 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 | Hi there, 2 | In this free and open source project I will create various advanced godot ui components. 3 | feel free to use it in your project! 4 | 5 | ## 003- Mograph Component 6 | ## 002- Custom Window Bar 7 | ## 001- Draggable Card Component 8 | -------------------------------------------------------------------------------- /boghma/c4d/c4d_interact.pyp: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | __author__ = "JACKADUX" 4 | import os 5 | import c4d 6 | import sys 7 | import json 8 | import socket 9 | from importlib import reload 10 | from pathlib import Path 11 | from ctypes import pythonapi, c_int, py_object 12 | from c4d.threading import C4DThread 13 | 14 | # 查找导入共用库 15 | PLUGINPATH, f = os.path.split(__file__) 16 | LIBS_PATH = os.path.join(PLUGINPATH, "lib") 17 | TEMP_QUEUE_PATH = os.path.join(PLUGINPATH, "res", "_temp.json") 18 | CONFIGS_PATH = os.path.join(PLUGINPATH, "res", "configs.json") 19 | 20 | 21 | PLUGINID: int = 10000000 22 | PLUGINNAME: str = "Helper" 23 | PLUGINVERSION: str = "0.1.0" 24 | PLUGINHELP: str = "" 25 | 26 | 27 | _sh_thread = None 28 | ID_SP_EVENT = 1 29 | 30 | sys.path.insert(0, LIBS_PATH) 31 | try: 32 | pass 33 | finally: 34 | sys.path.pop(0) 35 | 36 | 37 | def read_json(source_path): 38 | with open(source_path, 'r', encoding='UTF-8') as file: 39 | strings = file.read() 40 | file.close() 41 | return json.loads(strings) 42 | 43 | def write_json(source_path, data): 44 | with open(source_path, 'w', encoding='UTF-8') as file: 45 | file.write(json.dumps(data, sort_keys=True, indent=4,separators=(', ', ':'), ensure_ascii=0)) 46 | file.close() 47 | 48 | class Listener(C4DThread): 49 | _stopThread = False 50 | _conn = None 51 | _addr = None 52 | _socket = None 53 | 54 | def __init__(self, host, port) -> None: 55 | super().__init__() 56 | self.host = host 57 | self.port = port 58 | 59 | def OpenSocket(self): 60 | self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 61 | self._socket.bind((self.host, self.port)) 62 | self._socket.listen(5) 63 | self._socket.settimeout(1) 64 | return (self._socket is not None) 65 | 66 | def CloseSocket(self): 67 | # close connection 68 | if self._conn is not None: 69 | self._conn.close() 70 | # close socket 71 | if self._socket is not None: 72 | self._socket.close() 73 | # signal the thread 74 | self._stopThread = True 75 | 76 | 77 | def TestDBreak(self): 78 | return self._stopThread 79 | 80 | def Main(self): 81 | # check for connections 82 | while not self.TestBreak(): 83 | try: 84 | self._conn, self._addr = self._socket.accept() 85 | except Exception as err: 86 | continue 87 | while not self.TestBreak(): 88 | #check for data 89 | data = self._conn.recv(4096) 90 | if not data: 91 | break 92 | write_json(TEMP_QUEUE_PATH, json.loads(data.decode('utf-8'))) 93 | c4d.SpecialEventAdd(PLUGINID, ID_SP_EVENT, 0) 94 | 95 | self._conn.close() 96 | 97 | class MyMessageData(c4d.plugins.MessageData): 98 | 99 | 100 | def CoreMessage(self, id, bc): 101 | 102 | if id == PLUGINID: 103 | pythonapi.PyCapsule_GetPointer.restype = c_int 104 | pythonapi.PyCapsule_GetPointer.argtypes = [py_object] 105 | P1MSG_UN1 = bc.GetVoid(c4d.BFM_CORE_PAR1) 106 | P1MSG_EN1 = pythonapi.PyCapsule_GetPointer(P1MSG_UN1, None) 107 | if P1MSG_EN1 == ID_SP_EVENT: 108 | data = read_json(TEMP_QUEUE_PATH) 109 | 110 | c4d.EventAdd() 111 | return True 112 | 113 | 114 | class Main_CMD(c4d.plugins.CommandData): 115 | 116 | def Execute(self, doc): 117 | return True 118 | 119 | def RestoreLayout(self, sec_ref): 120 | return self.GetDialog().Restore(pluginid=PLUGINID, secret=sec_ref) 121 | 122 | 123 | 124 | def PluginMessage(id, data): 125 | global _sh_thread 126 | 127 | if id == c4d.C4DPL_PROGRAM_STARTED: 128 | config = read_json(CONFIGS_PATH) 129 | _sh_thread = Listener(config["host"], config["port"]) 130 | if _sh_thread.OpenSocket(): 131 | _sh_thread.Start(c4d.THREADMODE_ASYNC, c4d.THREADPRIORITY_LOWEST) 132 | return True 133 | 134 | if id == c4d.C4DPL_ENDPROGRAM: 135 | if (_sh_thread): 136 | _sh_thread.End() 137 | _sh_thread.CloseSocket() 138 | return True 139 | 140 | 141 | if __name__ == '__main__': 142 | icon_path = os.path.join(PLUGINPATH, "icon.png") 143 | icon = c4d.bitmaps.BaseBitmap() 144 | icon.InitWith(icon_path) 145 | c4d.plugins.RegisterCommandPlugin(id = PLUGINID, 146 | str = PLUGINNAME, 147 | info = 0, 148 | icon = icon, 149 | help = PLUGINHELP, 150 | dat = Main_CMD()) 151 | c4d.plugins.RegisterMessagePlugin(id=PLUGINID+1, str="", info=0, dat=MyMessageData()) -------------------------------------------------------------------------------- /boghma/dialogs/custom_confirm_dialog.gd: -------------------------------------------------------------------------------- 1 | class_name CustomConfirmationDialog extends ConfirmationDialog 2 | 3 | enum ResultCode { 4 | None, 5 | OK, 6 | CANCEL, 7 | DISCARD, 8 | } 9 | var result := ResultCode.None 10 | 11 | func init_with(_title:String, _dialog_text:String) -> ResultHelper: 12 | var result_helper := ResultHelper.new() 13 | confirmed.connect(func(): 14 | result = ResultCode.OK 15 | result_helper.success() 16 | queue_free() 17 | ) 18 | canceled.connect(func(): 19 | result = ResultCode.CANCEL 20 | result_helper.success() 21 | queue_free() 22 | 23 | ) 24 | title = _title 25 | dialog_text = _dialog_text # 26 | initial_position = Window.WINDOW_INITIAL_POSITION_CENTER_MAIN_WINDOW_SCREEN 27 | unresizable = true 28 | return result_helper 29 | 30 | func init_with_discard(_title:String, _dialog_text:String) -> ResultHelper: 31 | var result_helper := init_with(_title, _dialog_text) 32 | add_button("Discard", true, "Discard") 33 | custom_action.connect(func(_acname:String): 34 | result = ResultCode.DISCARD 35 | hide() 36 | result_helper.success() 37 | queue_free() 38 | ) 39 | return result_helper 40 | -------------------------------------------------------------------------------- /boghma/dialogs/file_dialog.gd: -------------------------------------------------------------------------------- 1 | class_name Utils 2 | 3 | #--------------------------------------------------------------------------------------------------- 4 | static func file_dialog(title:String="Files", filter=[], mode=DisplayServer.FILE_DIALOG_MODE_OPEN_FILE): 5 | var files = [] 6 | var _on_folder_selected = func(status:bool, selected_paths:PackedStringArray, _selected_filter_index:int): 7 | if not status: 8 | return 9 | files.append_array(selected_paths) 10 | DisplayServer.file_dialog_show(title,"","",false, 11 | mode, 12 | filter, 13 | _on_folder_selected) 14 | return files 15 | -------------------------------------------------------------------------------- /boghma/finite_state_machine/base_state.gd: -------------------------------------------------------------------------------- 1 | class_name BaseState extends RefCounted 2 | 3 | var state_machine:BaseStateMachine 4 | var agent:Node: 5 | get: return state_machine.agent 6 | 7 | 8 | func enter(msg:={}): 9 | pass 10 | 11 | func exit(): 12 | pass 13 | 14 | func update(delta:float): 15 | pass 16 | 17 | func transition_to(state_index:int, msg:={}): 18 | state_machine.transition_to(state_index, msg) 19 | -------------------------------------------------------------------------------- /boghma/finite_state_machine/base_state_machine.gd: -------------------------------------------------------------------------------- 1 | class_name BaseStateMachine extends Node 2 | 3 | @export var agent:Node = self 4 | var current_state:BaseState 5 | var states := {} 6 | 7 | func _process(delta): 8 | if not current_state: return 9 | current_state.update(delta) 10 | 11 | func launch(state_index:int=0): 12 | current_state = states[state_index] 13 | current_state.enter() 14 | 15 | func add_state(state_index:int, state:BaseState): 16 | states[state_index] = state 17 | state.state_machine = self 18 | 19 | func remove_state(state_index:int): 20 | states[state_index].state_machine = null 21 | states.erase(state_index) 22 | 23 | func transition_to(state_index:int, msg:={}): 24 | current_state.exit() 25 | current_state = states[state_index] 26 | current_state.enter(msg) 27 | 28 | -------------------------------------------------------------------------------- /boghma/model/base_hierarchy.gd: -------------------------------------------------------------------------------- 1 | class_name BaseHierarchy 2 | 3 | var _parent:BaseHierarchy=null 4 | var _children:Array = [] 5 | 6 | enum DragDrop { 7 | BEFORE=-1, 8 | UNDER=0, 9 | AFTER=1, 10 | UNDER_FIRST=2, 11 | } 12 | 13 | #region Hierarchy 14 | func path_to_root(revered:=false, inclued_item:=true) -> Array: 15 | # 默认 [self -> root] , reversed [root, self] 16 | var path_list = [] 17 | if inclued_item: 18 | path_list = [self] 19 | var parent = get_parent() 20 | while parent: 21 | path_list.append(parent) 22 | parent = parent.get_parent() 23 | if revered: 24 | path_list.reverse() 25 | return path_list 26 | 27 | func is_ancestor_of(data:BaseHierarchy) -> bool: 28 | return self in data.path_to_root(false, false) 29 | 30 | func get_parent() -> BaseHierarchy: 31 | return _parent 32 | 33 | func add_child(child: BaseHierarchy) -> Error: 34 | if child in _children: 35 | return FAILED 36 | if child.get_parent(): 37 | return FAILED 38 | if child.is_ancestor_of(self): 39 | return FAILED 40 | _children.append(child) 41 | child._parent = self 42 | return OK 43 | 44 | func remove_child(child: BaseHierarchy) -> Error: 45 | if child not in _children: 46 | return FAILED 47 | _children.erase(child) 48 | child._parent = null 49 | return OK 50 | 51 | func get_index() -> int: 52 | if not _parent: 53 | return -1 54 | return _parent._children.find(self) 55 | 56 | func get_children() -> Array: 57 | return _children.duplicate() 58 | 59 | func get_child_count() -> int: 60 | return _children.size() 61 | 62 | func get_child(index:int): 63 | return _children[index] 64 | 65 | func move_child(child: BaseHierarchy, to_index: int) -> Error: 66 | if child not in _children: 67 | return FAILED 68 | var current_index = _children.find(child) 69 | if current_index == -1 or current_index == to_index: 70 | return FAILED 71 | _children.erase(child) 72 | to_index = clamp(to_index, 0, _children.size()) 73 | if to_index >= _children.size(): 74 | _children.append(child) 75 | else: 76 | _children.insert(to_index, child) 77 | return OK 78 | 79 | func move_before(other:BaseHierarchy) -> Error: 80 | if other == self: 81 | return FAILED 82 | var other_parent := other.get_parent() 83 | if other_parent == self: 84 | return FAILED 85 | assert(other_parent, "other_parent 必须存在才能用这个方法") 86 | if not _parent: 87 | other_parent.add_child(self) 88 | elif _parent != other_parent: 89 | _parent.remove_child(self) 90 | other_parent.add_child(self) 91 | if get_index() != other.get_index(): 92 | other_parent.move_child(self, other.get_index()) 93 | return OK 94 | 95 | func move_after(other:BaseHierarchy) -> Error: 96 | if other == self: 97 | return FAILED 98 | var other_parent := other.get_parent() 99 | if other_parent == self: 100 | return FAILED 101 | assert(other_parent, "other_parent 必须存在才能用这个方法") 102 | if not _parent: 103 | other_parent.add_child(self) 104 | elif _parent != other_parent: 105 | _parent.remove_child(self) 106 | other_parent.add_child(self) 107 | var other_index = other.get_index() 108 | if get_index() < other_index: 109 | other_parent.move_child(self, other.get_index()) 110 | else: 111 | other_parent.move_child(self, other.get_index()+1) 112 | return OK 113 | 114 | func drag_to(drop:BaseHierarchy, section:DragDrop) -> Error: 115 | if drop == self: 116 | return FAILED 117 | match section: 118 | DragDrop.BEFORE: 119 | return move_before(drop) 120 | DragDrop.UNDER: 121 | var parent = get_parent() 122 | if parent: 123 | parent.remove_child(self) 124 | drop.add_child(self) 125 | return OK 126 | DragDrop.AFTER: 127 | return move_after(drop) 128 | DragDrop.UNDER_FIRST: 129 | var parent = get_parent() 130 | if parent: 131 | parent.remove_child(self) 132 | drop.add_child(self) 133 | drop.move_child(self, 0) 134 | return OK 135 | return FAILED 136 | 137 | func get_prev() -> BaseHierarchy: 138 | var index = get_index()-1 139 | if index >= 0: 140 | return get_parent().get_child(index) 141 | return null 142 | 143 | func get_next() -> BaseHierarchy: 144 | var index = get_index()+1 145 | if index < get_parent().get_child_count(): 146 | return get_parent().get_child(index) 147 | return null 148 | 149 | func iterate(): 150 | return Iterator.new(self) 151 | 152 | #endregion 153 | class Iterator: 154 | var ori:BaseHierarchy 155 | var _current:BaseHierarchy 156 | 157 | func _init(current): 158 | ori = current 159 | _current = current 160 | 161 | func _iter_init(arg): 162 | _current = ori 163 | return _current 164 | 165 | func _iter_next(arg): 166 | if _current.get_child_count() != 0: 167 | _current = _current.get_child(0) 168 | return true 169 | if _current == ori: 170 | return false 171 | var parent = _current.get_parent() 172 | if not parent: 173 | return false 174 | var next = _current.get_next() 175 | if next: 176 | _current = next 177 | return true 178 | while true: 179 | if parent == ori: 180 | return false 181 | var pn = parent.get_next() 182 | if pn: 183 | _current = pn 184 | return true 185 | parent = parent.get_parent() 186 | return false 187 | 188 | func _iter_get(arg): 189 | return _current 190 | 191 | 192 | static func print_tree(element:BaseHierarchy, level:int=0): 193 | print("\t".repeat(level), element) 194 | for child in element.get_children(): 195 | print_tree(child, level+1) 196 | 197 | ##================================================================================================== 198 | static func undoredo_add(undoredo:UndoRedo, item, parent, action_name:="Add"): 199 | undoredo.create_action(action_name) 200 | undoredo.add_do_method(func(): 201 | parent.add_child(item) 202 | ) 203 | undoredo.add_do_reference(item) 204 | undoredo.add_undo_method(func(): 205 | parent.remove_child(item) 206 | ) 207 | undoredo.commit_action() 208 | return item 209 | 210 | 211 | static func undoredo_remove(undoredo:UndoRedo, item, action_name:="Remove"): 212 | var parent = item.get_parent() 213 | if not parent: 214 | return 215 | undoredo.create_action(action_name) 216 | undoredo.add_do_method(func(): 217 | parent.remove_child(item) 218 | ) 219 | undoredo.add_undo_method(func(): 220 | parent.add_child(item) 221 | ) 222 | undoredo.add_undo_reference(item) 223 | undoredo.commit_action() 224 | 225 | 226 | static func undoredo_drag(undoredo:UndoRedo, drags:Array, drop, drop_mode:BaseHierarchy.DragDrop, action_name:="ChangeHierarchy"): 227 | undoredo.create_action(action_name) 228 | # undo 229 | for item in drags: 230 | var _drop = item.get_prev() 231 | var _mode = BaseHierarchy.DragDrop.AFTER 232 | if not _drop: 233 | _drop = item.get_parent() 234 | _mode = BaseHierarchy.DragDrop.UNDER_FIRST 235 | undoredo.add_undo_method(item.drag_to.bind(_drop, _mode)) 236 | # do 237 | for item in drags: 238 | var _drop = drop 239 | var _mode = drop_mode 240 | if item.get_index() != 0: 241 | _drop = drags[item.get_index()-1] 242 | _mode = BaseHierarchy.DragDrop.AFTER 243 | undoredo.add_do_method(item.drag_to.bind(_drop, _mode)) 244 | undoredo.commit_action() 245 | 246 | 247 | -------------------------------------------------------------------------------- /boghma/model/uniform_data.gd: -------------------------------------------------------------------------------- 1 | class_name UniformData extends BaseHierarchy 2 | 3 | var _id:String="" 4 | var _type:int = 0 5 | var _type_string:String = "" 6 | 7 | func _to_string() -> String: 8 | return "<#%s>:%s"%[get_type_string(), get_id()] 9 | 10 | func get_id(): 11 | if not _id: 12 | _id = str(get_instance_id()) 13 | return _id 14 | 15 | func get_type() -> int: 16 | return _type 17 | 18 | func get_type_string() -> String: 19 | return _type_string 20 | 21 | -------------------------------------------------------------------------------- /boghma/mvc/action_message.gd: -------------------------------------------------------------------------------- 1 | # 用于向上传递命令请求 2 | class_name ActionMessage extends BaseMessage 3 | 4 | var _is_process:bool=false 5 | func as_process(value:=true): 6 | _is_process = value 7 | return self 8 | func is_process(): 9 | return _is_process 10 | 11 | #--------------------------------------------------------------------------------------------------- 12 | class BundleAction extends ActionMessage: 13 | # 可以将其他的action 作为 bundle 一起发送 14 | # undoredo只会记录一次 15 | var action_name:String="" 16 | var messages : Array = [] 17 | func _to_string(): 18 | return "BundleAction" 19 | 20 | func add_action(msg:ActionMessage): 21 | messages.append(msg) 22 | 23 | static func empty(name:String): 24 | return BundleAction.new([name, []]) 25 | 26 | #--------------------------------------------------------------------------------------------------- 27 | class Action extends ActionMessage: 28 | var data 29 | func _to_string(): 30 | return "Action" 31 | 32 | 33 | -------------------------------------------------------------------------------- /boghma/mvc/base_item.gd: -------------------------------------------------------------------------------- 1 | class_name BaseItem extends UniformData 2 | 3 | var title:String="" 4 | 5 | #--------------------------------------------------------------------------------------------------- 6 | func set_title(value:String): 7 | title = value 8 | 9 | #--------------------------------------------------------------------------------------------------- 10 | func get_title(): 11 | return title 12 | 13 | #--------------------------------------------------------------------------------------------------- 14 | func remove(): 15 | get_parent().remove_child(self) 16 | 17 | #--------------------------------------------------------------------------------------------------- 18 | func deserialization(value:Dictionary): 19 | set_title(value.get("title", "")) 20 | 21 | #--------------------------------------------------------------------------------------------------- 22 | func serialization() -> Dictionary: 23 | var pid = null 24 | if get_parent(): 25 | pid = get_parent().get_id() 26 | 27 | return { 28 | "id":get_id(), 29 | "type":get_type(), 30 | "pid":pid, 31 | "title":title 32 | } 33 | 34 | 35 | #=================================================================================================== 36 | class GroupItem extends BaseItem:pass 37 | 38 | -------------------------------------------------------------------------------- /boghma/mvc/base_message.gd: -------------------------------------------------------------------------------- 1 | class_name BaseMessage 2 | 3 | 4 | # signal message_sended(msg:BaseMessage) 5 | # #--------------------------------------------------------------------------------------------------- 6 | # func handle_message(msg:BaseMessage): 7 | # pass 8 | # #--------------------------------------------------------------------------------------------------- 9 | # func send_message(msg:BaseMessage): 10 | # message_sended.emit(msg) 11 | 12 | 13 | var _kwargs := {} 14 | 15 | func _init(args:Array, kwargs:={}): 16 | var index = 0 17 | for arg in self.get_property_list(): 18 | if (arg.usage & PROPERTY_USAGE_SCRIPT_VARIABLE) != PROPERTY_USAGE_SCRIPT_VARIABLE: 19 | continue 20 | if arg.name.begins_with("_"): 21 | continue 22 | self.set(arg.name, args[index]) 23 | assert(self.get(arg.name) == args[index], 24 | "参数类型必须是一致的,否则 set 会无效 。Array[String] != Array" 25 | ) 26 | index += 1 27 | 28 | if index < args.size(): 29 | push_error("not all args being used! %d/%d"%[index, args.size()]) 30 | _kwargs = kwargs 31 | 32 | func get_kwargs(key:String): 33 | # 保证调用时这个值一定存在,否则会报错 34 | return _kwargs[key] 35 | 36 | 37 | func _to_string(): 38 | return "< BaseMessage#%d >"%get_instance_id() 39 | 40 | 41 | 42 | static func connect_message_handler(sender, handler): 43 | assert(handler.has_method("handle_message")) 44 | sender.message_sended.connect(func(msg:BaseMessage): 45 | #prints(sender, "[Send]:", msg, "[To]:", handler) 46 | handler.handle_message(msg) 47 | ) 48 | -------------------------------------------------------------------------------- /boghma/mvc/controller.gd: -------------------------------------------------------------------------------- 1 | class_name Contoller 2 | 3 | signal message_sended(msg:BaseMessage) 4 | 5 | var undoredo:=UndoRedo.new() 6 | 7 | #--------------------------------------------------------------------------------------------------- 8 | func _init(): 9 | undoredo.max_steps = 50 10 | 11 | #--------------------------------------------------------------------------------------------------- 12 | func handle_message(msg:BaseMessage): 13 | if msg is ActionMessage.BundleAction: 14 | undoredo.create_action(msg.action_name) 15 | for _msg in msg.messages: 16 | handle_message(_msg) 17 | undoredo.commit_action() 18 | 19 | #--------------------------------------------------------------------------------------------------- 20 | func send_message(msg:BaseMessage): 21 | message_sended.emit(msg) 22 | 23 | ##================================================================================================== 24 | func initialize(): 25 | send_message(Update.Initialize.new([])) 26 | 27 | 28 | -------------------------------------------------------------------------------- /boghma/mvc/item_factory.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | var _factory:={} 4 | 5 | 6 | enum ItemType { 7 | BaseItem, 8 | } 9 | 10 | #--------------------------------------------------------------------------------------------------- 11 | func _init(): 12 | var simple_register := func(object:Object, type:ItemType): 13 | register(type, func(): 14 | var instance = object.new() 15 | instance._type = type 16 | instance._type_string = ItemType.keys()[type] 17 | return instance 18 | ) 19 | 20 | simple_register.call(BaseItem, ItemType.BaseItem) 21 | 22 | 23 | #--------------------------------------------------------------------------------------------------- 24 | func register(type:int, create_fn:Callable): 25 | _factory[type] = create_fn 26 | 27 | #--------------------------------------------------------------------------------------------------- 28 | func unregister(type): 29 | if type in _factory: 30 | _factory.erase(type) 31 | 32 | #--------------------------------------------------------------------------------------------------- 33 | func create(type:int): 34 | if _factory.get(type): 35 | return _factory[type].call() 36 | 37 | 38 | #--------------------------------------------------------------------------------------------------- 39 | func serialization(item:BaseItem): 40 | var item_datas = [] 41 | for sub_item:BaseItem in item.iterate(): 42 | var item_data = sub_item.serialization() 43 | item_datas.append(item_data) 44 | return item_datas 45 | 46 | #--------------------------------------------------------------------------------------------------- 47 | func deserialization(item_datas:Array): 48 | var temp_map = {} 49 | var root_item:BaseItem 50 | for item_data in item_datas: 51 | var item :BaseItem = ItemFactory.create(item_data.type) 52 | temp_map[item_data.id] = item 53 | if not root_item: 54 | root_item = item 55 | var parent = temp_map.get(item_data.pid) 56 | if parent: 57 | parent.add_child(item) 58 | item.deserialization(item_data) 59 | return root_item 60 | 61 | -------------------------------------------------------------------------------- /boghma/mvc/update_message.gd: -------------------------------------------------------------------------------- 1 | # 用于向下传递信息 2 | class_name UpdateMessage extends BaseMessage 3 | 4 | #--------------------------------------------------------------------------------------------------- 5 | class Update extends UpdateMessage: 6 | var data 7 | func _to_string(): 8 | return "Update" 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /boghma/scripts/custom_iterator.gd: -------------------------------------------------------------------------------- 1 | class_name CustomIterator 2 | 3 | class Enumerate: 4 | var array 5 | var index 6 | 7 | func _init(array:Array): 8 | self.array = array 9 | 10 | func _iter_init(arg): 11 | index = 0 12 | return array 13 | 14 | func _iter_next(arg): 15 | index += 1 16 | return index < array.size() 17 | 18 | func _iter_get(arg): 19 | return {"index":index, "value":array[index]} 20 | 21 | 22 | 23 | class DirectoryIterator: 24 | var ori_directory :String 25 | var current :String 26 | var stack := [] 27 | var current_dir:DirAccess 28 | 29 | func _init(directory:String): 30 | ori_directory = directory 31 | 32 | func _iter_init(arg): 33 | assert(ori_directory and DirAccess.dir_exists_absolute(ori_directory), 34 | "not valid directory: '%s'"% ori_directory) 35 | current = ori_directory 36 | current_dir = DirAccess.open(ori_directory) 37 | current_dir.list_dir_begin() 38 | stack = [] 39 | return true 40 | 41 | func _iter_next(arg): 42 | var file_name = current_dir.get_next() 43 | if file_name == "": 44 | while true: 45 | if not stack: 46 | return false 47 | current_dir.list_dir_end() 48 | current_dir = stack.pop_back() 49 | file_name = current_dir.get_next() 50 | if file_name: 51 | break 52 | current = current_dir.get_current_dir() +"/"+ file_name 53 | if current_dir.current_is_dir(): 54 | stack.append(current_dir) 55 | current_dir = DirAccess.open(current) 56 | current_dir.list_dir_begin() 57 | 58 | return true 59 | 60 | func _iter_get(arg): 61 | return current 62 | 63 | 64 | class TreeStructureIterator: 65 | var current 66 | var ori 67 | 68 | func _init(current:TreeItem): 69 | self.ori = current 70 | self.current = current 71 | 72 | func _iter_init(arg): 73 | current = ori 74 | return current 75 | 76 | func _iter_next(arg): 77 | var down = current.get_first_child() 78 | if down: 79 | current = down 80 | return true 81 | var next = current.get_next() 82 | if next: 83 | current = next 84 | return true 85 | while true: 86 | var parent = current.get_parent() 87 | if not parent: 88 | return false 89 | next = parent.get_next() 90 | if next: 91 | current = next 92 | return true 93 | current = parent 94 | return false 95 | 96 | func _iter_get(arg): 97 | return current 98 | 99 | -------------------------------------------------------------------------------- /boghma/scripts/factory.gd: -------------------------------------------------------------------------------- 1 | class_name Factory 2 | 3 | var _factory:={} 4 | 5 | var custom_register:Callable 6 | var custom_create:Callable 7 | 8 | func register(type:int, create:Callable): 9 | _factory[type] = create 10 | 11 | func unregister(type:int): 12 | if type in _factory: 13 | _factory.erase(type) 14 | 15 | func create(type:int): 16 | if _factory.get(type): 17 | return _factory[type].call() 18 | -------------------------------------------------------------------------------- /boghma/scripts/free_parent_when_start.gd: -------------------------------------------------------------------------------- 1 | class_name FPWS extends Node 2 | 3 | @export var enable:= true 4 | 5 | func _ready() -> void: 6 | if enable or not OS.is_debug_build(): 7 | get_parent().queue_free() 8 | 9 | -------------------------------------------------------------------------------- /boghma/scripts/funfile.gd: -------------------------------------------------------------------------------- 1 | class_name FunFile 2 | 3 | static func delet_folder(source_folder:String) -> bool: 4 | assert(DirAccess.dir_exists_absolute(source_folder)) 5 | for file in DirAccess.get_files_at(source_folder): 6 | DirAccess.remove_absolute(source_folder.path_join(file)) 7 | for folder in DirAccess.get_directories_at(source_folder): 8 | delet_folder(source_folder.path_join(folder)) 9 | DirAccess.remove_absolute(source_folder) 10 | return true 11 | 12 | static func unzip_file(source_file:String, target_path:String) -> bool: 13 | assert(DirAccess.dir_exists_absolute(target_path)) 14 | var reader := ZIPReader.new() 15 | var err := reader.open(source_file) 16 | if err != OK: 17 | return false 18 | var dir_access = DirAccess.open(target_path) 19 | for file in reader.get_files(): 20 | if file.get_extension(): 21 | file = file.get_base_dir() 22 | dir_access.make_dir_recursive(file) 23 | for file in reader.get_files(): 24 | if file.get_extension(): 25 | var file_access = FileAccess.open(target_path.path_join(file),FileAccess.WRITE) 26 | if not file_access: 27 | push_error("unzip_file skip '%s'"%[file]) 28 | continue 29 | file_access.store_buffer(reader.read_file(file)) 30 | file_access.close() 31 | reader.close() 32 | return true 33 | 34 | -------------------------------------------------------------------------------- /boghma/scripts/json_helper.gd: -------------------------------------------------------------------------------- 1 | class_name JsonHelper extends Resource 2 | 3 | static func load_meta(json_path): 4 | if not FileAccess.file_exists(json_path): 5 | return {} 6 | var file = FileAccess.open(json_path, FileAccess.READ) 7 | return JSON.parse_string(file.get_as_text()) 8 | 9 | static func save_meta(json_path, file_data): 10 | var file = FileAccess.open(json_path, FileAccess.WRITE) 11 | file.store_line(JSON.stringify(file_data)) 12 | -------------------------------------------------------------------------------- /boghma/scripts/result_helper.gd: -------------------------------------------------------------------------------- 1 | class_name ResultHelper 2 | 3 | signal any_result 4 | signal successed 5 | signal failed 6 | signal error_occurred 7 | 8 | signal updated(data) 9 | 10 | var state := 0 11 | 12 | func _init(): 13 | successed.connect(emit_signal.bind("any_result")) 14 | failed.connect(emit_signal.bind("any_result")) 15 | error_occurred.connect(emit_signal.bind("any_result")) 16 | 17 | func is_nothing_happend(): 18 | return state == 0 19 | 20 | func is_successed(): 21 | return state == 1 22 | 23 | func is_failed(): 24 | return state == 2 25 | 26 | func is_error_occurred(): 27 | return state == 3 28 | 29 | func success(): 30 | state = 1 31 | successed.emit() 32 | 33 | func fail(): 34 | state = 2 35 | failed.emit() 36 | 37 | func error(): 38 | state = 3 39 | error_occurred.emit() 40 | 41 | func update(data): 42 | updated.emit(data) 43 | -------------------------------------------------------------------------------- /boghma/scripts/scene_manager.gd: -------------------------------------------------------------------------------- 1 | class_name ScenesManager extends Node 2 | 3 | signal scene_changed 4 | 5 | @export var agent:Node 6 | 7 | var current_scene:Node 8 | 9 | func set_current_scene(scene:PackedScene): 10 | if current_scene: 11 | if current_scene.has_method("scene_change_exit"): 12 | current_scene.scene_change_exit() 13 | else: 14 | agent.remove_child(current_scene) 15 | current_scene.queue_free() 16 | 17 | current_scene = scene.instantiate() 18 | agent.add_child(current_scene) 19 | if current_scene.has_method("scene_change_enter"): 20 | current_scene.scene_change_enter() 21 | scene_changed.emit() 22 | return current_scene 23 | 24 | -------------------------------------------------------------------------------- /boghma/scripts/structure.gd: -------------------------------------------------------------------------------- 1 | class_name Structure 2 | 3 | var _kwargs := {} 4 | func _init(args:Array, kwargs:={}): 5 | var index = 0 6 | for arg in self.get_property_list(): 7 | if (arg.usage & PROPERTY_USAGE_SCRIPT_VARIABLE) != PROPERTY_USAGE_SCRIPT_VARIABLE: 8 | continue 9 | if arg.name.begins_with("_"): 10 | continue 11 | self.set(arg.name, args[index]) 12 | assert(self.get(arg.name) == args[index], 13 | "参数类型必须是一致的,否则 set 会无效 。Array[String] != Array" 14 | ) 15 | index += 1 16 | 17 | if index < args.size(): 18 | push_error("not all args being used! %d/%d"%[index, args.size()]) 19 | _kwargs = kwargs 20 | 21 | func get_kwargs(key:String): 22 | # 保证调用时这个值一定存在,否则会报错 23 | return _kwargs[key] 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /boghma/scripts/thread_helper.gd: -------------------------------------------------------------------------------- 1 | class_name ThreadHelper 2 | 3 | var _thread := Thread.new() 4 | var _funcs := [] 5 | var _end := false 6 | var _holder :Node 7 | 8 | 9 | func _init(holder:Node): 10 | _holder = holder 11 | _holder.tree_exited.connect(end) 12 | 13 | func join_function(function:Callable, auto_start=true): 14 | _funcs.append(function) 15 | if auto_start: 16 | start() 17 | 18 | func start(): 19 | assert(_holder, "holder can't be none") 20 | _end = false 21 | if not _thread.is_alive(): 22 | if _thread.is_started(): 23 | _thread.wait_to_finish() 24 | _thread.start(_start_thread) 25 | 26 | func is_running(): 27 | return _thread.is_alive() 28 | 29 | func end(): 30 | _end_thread() 31 | 32 | func _start_thread(): 33 | while true: 34 | if not _funcs or _end: 35 | break 36 | var function = _funcs.pop_front() 37 | if function and function is Callable: 38 | function.call() 39 | 40 | func _end_thread(): 41 | # !! 切记在强制中断thread时调用 end_thread, 否则可能会崩溃 42 | _end = true 43 | _funcs = [] 44 | if _thread.is_started(): 45 | _thread.wait_to_finish() 46 | 47 | -------------------------------------------------------------------------------- /boghma/scripts/uuid.gd: -------------------------------------------------------------------------------- 1 | # https://github.com/binogure-studio/godot-uuid/tree/master 2 | """ 3 | MIT License 4 | 5 | Copyright (c) 2023 Xavier Sellier 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | """ 25 | 26 | # Note: The code might not be as pretty it could be, since it's written 27 | # in a way that maximizes performance. Methods are inlined and loops are avoided. 28 | class_name UUID 29 | 30 | const BYTE_MASK: int = 0b11111111 31 | 32 | static func uuidbin(): 33 | # 16 random bytes with the bytes on index 6 and 8 modified 34 | return [ 35 | randi() & BYTE_MASK, randi() & BYTE_MASK, randi() & BYTE_MASK, randi() & BYTE_MASK, 36 | randi() & BYTE_MASK, randi() & BYTE_MASK, ((randi() & BYTE_MASK) & 0x0f) | 0x40, randi() & BYTE_MASK, 37 | ((randi() & BYTE_MASK) & 0x3f) | 0x80, randi() & BYTE_MASK, randi() & BYTE_MASK, randi() & BYTE_MASK, 38 | randi() & BYTE_MASK, randi() & BYTE_MASK, randi() & BYTE_MASK, randi() & BYTE_MASK, 39 | ] 40 | 41 | static func uuidbinrng(rng: RandomNumberGenerator): 42 | return [ 43 | rng.randi() & BYTE_MASK, rng.randi() & BYTE_MASK, rng.randi() & BYTE_MASK, rng.randi() & BYTE_MASK, 44 | rng.randi() & BYTE_MASK, rng.randi() & BYTE_MASK, ((rng.randi() & BYTE_MASK) & 0x0f) | 0x40, rng.randi() & BYTE_MASK, 45 | ((rng.randi() & BYTE_MASK) & 0x3f) | 0x80, rng.randi() & BYTE_MASK, rng.randi() & BYTE_MASK, rng.randi() & BYTE_MASK, 46 | rng.randi() & BYTE_MASK, rng.randi() & BYTE_MASK, rng.randi() & BYTE_MASK, rng.randi() & BYTE_MASK, 47 | ] 48 | 49 | static func v4(): 50 | # 16 random bytes with the bytes on index 6 and 8 modified 51 | var b = uuidbin() 52 | 53 | return '%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x' % [ 54 | # low 55 | b[0], b[1], b[2], b[3], 56 | 57 | # mid 58 | b[4], b[5], 59 | 60 | # hi 61 | b[6], b[7], 62 | 63 | # clock 64 | b[8], b[9], 65 | 66 | # clock 67 | b[10], b[11], b[12], b[13], b[14], b[15] 68 | ] 69 | 70 | static func v4_rng(rng: RandomNumberGenerator): 71 | # 16 random bytes with the bytes on index 6 and 8 modified 72 | var b = uuidbinrng(rng) 73 | 74 | return '%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x' % [ 75 | # low 76 | b[0], b[1], b[2], b[3], 77 | 78 | # mid 79 | b[4], b[5], 80 | 81 | # hi 82 | b[6], b[7], 83 | 84 | # clock 85 | b[8], b[9], 86 | 87 | # clock 88 | b[10], b[11], b[12], b[13], b[14], b[15] 89 | ] 90 | 91 | var _uuid: Array 92 | 93 | func _init(rng := RandomNumberGenerator.new()) -> void: 94 | _uuid = uuidbinrng(rng) 95 | 96 | func as_array() -> Array: 97 | return _uuid.duplicate() 98 | 99 | func as_dict(big_endian := true) -> Dictionary: 100 | if big_endian: 101 | return { 102 | "low" : (_uuid[0] << 24) + (_uuid[1] << 16) + (_uuid[2] << 8 ) + _uuid[3], 103 | "mid" : (_uuid[4] << 8 ) + _uuid[5], 104 | "hi" : (_uuid[6] << 8 ) + _uuid[7], 105 | "clock": (_uuid[8] << 8 ) + _uuid[9], 106 | "node" : (_uuid[10] << 40) + (_uuid[11] << 32) + (_uuid[12] << 24) + (_uuid[13] << 16) + (_uuid[14] << 8 ) + _uuid[15] 107 | } 108 | else: 109 | return { 110 | "low" : _uuid[0] + (_uuid[1] << 8 ) + (_uuid[2] << 16) + (_uuid[3] << 24), 111 | "mid" : _uuid[4] + (_uuid[5] << 8 ), 112 | "hi" : _uuid[6] + (_uuid[7] << 8 ), 113 | "clock": _uuid[8] + (_uuid[9] << 8 ), 114 | "node" : _uuid[10] + (_uuid[11] << 8 ) + (_uuid[12] << 16) + (_uuid[13] << 24) + (_uuid[14] << 32) + (_uuid[15] << 40) 115 | } 116 | 117 | func as_string() -> String: 118 | return '%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x' % [ 119 | # low 120 | _uuid[0], _uuid[1], _uuid[2], _uuid[3], 121 | 122 | # mid 123 | _uuid[4], _uuid[5], 124 | 125 | # hi 126 | _uuid[6], _uuid[7], 127 | 128 | # clock 129 | _uuid[8], _uuid[9], 130 | 131 | # node 132 | _uuid[10], _uuid[11], _uuid[12], _uuid[13], _uuid[14], _uuid[15] 133 | ] 134 | 135 | func is_equal(other) -> bool: 136 | # Godot Engine compares Array recursively 137 | # There's no need for custom comparison here. 138 | return _uuid == other._uuid 139 | -------------------------------------------------------------------------------- /boghma/utils/http_request_helper.gd: -------------------------------------------------------------------------------- 1 | class_name HTTPRequestHelper extends HTTPRequest 2 | 3 | var result_helper:ResultHelper 4 | 5 | func _ready(): 6 | use_threads = true 7 | set_process(false) 8 | 9 | func _process(delta): 10 | var db = get_downloaded_bytes() 11 | result_helper.update(db) 12 | 13 | func get_request(url:String, method=HTTPClient.METHOD_GET) -> ResultHelper: 14 | var result_helper := ResultHelper.new() 15 | request_completed.connect(func(result, response_code, headers, body): 16 | queue_free() 17 | if response_code == 200: 18 | var data = {} 19 | if body: 20 | data = JSON.parse_string(body.get_string_from_utf8()) 21 | result_helper.set_meta("data", data) 22 | result_helper.success() 23 | else: 24 | result_helper.set_meta("data", {"result":result,"response_code":response_code}) 25 | result_helper.fail() 26 | ) 27 | var error = request(url, [], method) 28 | if error != OK: 29 | push_error("An error occurred in the HTTP request.") 30 | result_helper.error() 31 | queue_free() 32 | return result_helper 33 | 34 | func download(url:String, path:String) -> ResultHelper: 35 | result_helper = ResultHelper.new() 36 | request_completed.connect(func(result, response_code, headers, body): 37 | queue_free() 38 | set_process(false) 39 | if result == OK: 40 | result_helper.set_meta("data", {"path":path}) 41 | result_helper.success() 42 | else: 43 | push_error("Download Failed") 44 | result_helper.set_meta("data", {"result":result,"response_code":response_code}) 45 | result_helper.fail() 46 | ) 47 | set_download_file(path) 48 | var request = request(url) 49 | if request != OK: 50 | push_error("Http request error") 51 | result_helper.error() 52 | queue_free() 53 | else: 54 | set_process(true) 55 | return result_helper 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /boghma/utils/spring_function.gd: -------------------------------------------------------------------------------- 1 | class_name SpringFunction 2 | 3 | var _spring:float = 500 # 1000 4 | var _damp:float = 20 # 40 5 | 6 | var _displacement :float=0 7 | var _velocity :float=0 8 | 9 | func set_velocity(value:float, spring:float=500, damp:float=20): 10 | _spring = spring 11 | _damp = damp 12 | _velocity = value 13 | 14 | func get_displacment(): 15 | return _displacement 16 | 17 | func update(delta:float): 18 | var force = -_spring * _displacement - _damp*_velocity 19 | _velocity += force*delta 20 | _displacement += _velocity*delta 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /components/cell_grid.gd: -------------------------------------------------------------------------------- 1 | class_name CellGrid extends ScrollContainer 2 | 3 | const GAP = 2 4 | const SIDE_BAR_WIDTH :int = 32 5 | const TOP_BAR_HEIGHT :int = 32 6 | const MIN_LENGTH :int = 100 7 | 8 | var rs = RenderingServer 9 | var base_rid := rs.canvas_item_create() 10 | var items_rid := rs.canvas_item_create() 11 | var indicator_rid := rs.canvas_item_create() 12 | 13 | var SBOX_BG := get_base_stylebox(0) 14 | var SBOX_HOVERED := get_base_stylebox(1) 15 | var SBOX_SELECT := get_base_stylebox(2) 16 | var SBOX_RESIZE_BAR := get_base_stylebox(3) 17 | var SBOX_HOVERED_INDEX := get_base_stylebox(4) 18 | 19 | var FONT := get_base_font() 20 | 21 | const INTER_VARIABLE_FONT_SLNT_WGHT = preload("res://resource/fonts/inter/Inter-VariableFont_slnt,wght.ttf") 22 | 23 | var cells_offset :Vector2: 24 | get: return Vector2(SIDE_BAR_WIDTH+GAP, TOP_BAR_HEIGHT+GAP) 25 | 26 | var cell_x_count :int = 20 27 | var cell_y_count :int = 100 28 | #var bar_rects := {} 29 | var top_bar_rects := {} 30 | var side_bar_rects := {} 31 | 32 | var hovered_location := [] 33 | var select_locations := [] 34 | 35 | enum DrawDirty { 36 | ALL, 37 | BASE, 38 | ITEMS, 39 | INDICATOR, 40 | } 41 | var _dirty_base := false 42 | var _dirty_items := false 43 | var _dirty_indicator := false 44 | 45 | enum Actions { 46 | NORMAL, 47 | RESIZE_READY, 48 | RESIZE, 49 | } 50 | var action := Actions.NORMAL 51 | var _resize_bar_location := [] 52 | var _start_position := Vector2.ZERO 53 | 54 | var cell_items := {} 55 | 56 | var parent_rect:=Rect2() 57 | 58 | 59 | 60 | var control :Control 61 | 62 | #--------------------------------------------------------------------------------------------------- 63 | func _ready(): 64 | control = Control.new() 65 | add_child(control) 66 | control.mouse_filter = Control.MOUSE_FILTER_IGNORE 67 | control.size_flags_horizontal = Control.SIZE_EXPAND_FILL 68 | control.size_flags_vertical = Control.SIZE_EXPAND_FILL 69 | 70 | mouse_exited.connect(func(): 71 | hovered_location = [] 72 | queue_draw(DrawDirty.INDICATOR) 73 | ) 74 | get_h_scroll_bar().value_changed.connect(func(v): 75 | queue_draw() 76 | ) 77 | get_v_scroll_bar().value_changed.connect(func(v): 78 | queue_draw() 79 | ) 80 | resized.connect(func(): 81 | queue_draw() 82 | ) 83 | 84 | rs.canvas_item_set_parent(base_rid, control.get_canvas_item()) 85 | rs.canvas_item_set_parent(items_rid, control.get_canvas_item()) 86 | rs.canvas_item_set_parent(indicator_rid, control.get_canvas_item()) 87 | 88 | generate_bars() 89 | queue_draw() 90 | 91 | # 92 | var DEBUG_TEXTURE = preload("res://resource/place_holder/comp/1000.png") 93 | for x in cell_x_count: 94 | for y in cell_y_count: 95 | if randf() > 0.5: 96 | set_lable([x, y], "dfas123543dfasdfadfasgcxdfasdfa111121dfasdfasdfadfasdfa78378sdfa") 97 | else: 98 | set_texture([x, y], DEBUG_TEXTURE) 99 | 100 | 101 | #--------------------------------------------------------------------------------------------------- 102 | func set_texture(location:Array, value:Texture2D): 103 | cell_items[location] = value 104 | 105 | #--------------------------------------------------------------------------------------------------- 106 | func set_lable(location:Array, value:String): 107 | cell_items[location] = value 108 | 109 | #--------------------------------------------------------------------------------------------------- 110 | func _exit_tree(): 111 | rs.free_rid(base_rid) 112 | rs.free_rid(items_rid) 113 | rs.free_rid(indicator_rid) 114 | 115 | #--------------------------------------------------------------------------------------------------- 116 | func queue_draw(draw_dirty:=DrawDirty.ALL): 117 | match draw_dirty: 118 | DrawDirty.ALL: 119 | _dirty_base = true 120 | _dirty_items = true 121 | _dirty_indicator = true 122 | DrawDirty.BASE: 123 | _dirty_base = true 124 | DrawDirty.ITEMS: 125 | _dirty_items = true 126 | DrawDirty.INDICATOR: 127 | _dirty_indicator = true 128 | 129 | #--------------------------------------------------------------------------------------------------- 130 | func _process(delta): 131 | parent_rect = Rect2(-control.position, size) 132 | if _dirty_base: 133 | _dirty_base = false 134 | draw_cell_grid() 135 | if _dirty_items: 136 | _dirty_items = false 137 | draw_items() 138 | if _dirty_indicator: 139 | _dirty_indicator = false 140 | draw_indicator() 141 | 142 | 143 | 144 | #--------------------------------------------------------------------------------------------------- 145 | func _gui_input(event): 146 | if event is InputEventMouseMotion and event.button_mask == MOUSE_BUTTON_NONE: 147 | action = Actions.NORMAL 148 | var hovered = get_hovered() 149 | _resize_bar_location = get_resize_bar_location(hovered) 150 | if hovered == hovered_location: 151 | return 152 | hovered_location = hovered 153 | queue_draw(DrawDirty.INDICATOR) 154 | 155 | elif event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.is_pressed(): 156 | _start_position = control.get_local_mouse_position() 157 | match action: 158 | Actions.NORMAL: 159 | check_select() 160 | queue_draw(DrawDirty.INDICATOR) 161 | Actions.RESIZE_READY: 162 | action = Actions.RESIZE 163 | 164 | 165 | elif event is InputEventMouseMotion and event.button_mask != MOUSE_BUTTON_NONE: 166 | if action == Actions.RESIZE: 167 | var delta = event.relative as Vector2 168 | if delta.is_zero_approx(): 169 | return 170 | for location:Array in _resize_bar_location: 171 | var x = location[0] 172 | var y = location[1] 173 | var rect:Rect2 174 | if x == -1: # SIDE 175 | rect = side_bar_rects[location] 176 | set_side_bar_size(y, rect.size.y + delta.y) 177 | elif y == -1: # TOP 178 | rect = top_bar_rects[location] 179 | set_top_bar_size(x, rect.size.x + delta.x) 180 | queue_draw(DrawDirty.ALL) 181 | 182 | elif event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.is_released(): 183 | if action == Actions.RESIZE: 184 | #queue_draw(DrawDirty.ALL) 185 | pass 186 | 187 | 188 | #--------------------------------------------------------------------------------------------------- 189 | func get_resize_bar_location(location:Array): 190 | mouse_default_cursor_shape = CURSOR_ARROW 191 | var mp := control.get_local_mouse_position() 192 | var gap = 20 # 拖拽距离 193 | if not location: 194 | return [] 195 | 196 | var resize_bar_location = [] 197 | var rect:Rect2 = get_cell_rect(location) 198 | var dis = (rect.end - mp).abs() 199 | 200 | if location[0] == -1: # side 201 | if dis.y <= gap: 202 | mouse_default_cursor_shape = CURSOR_VSIZE 203 | action = Actions.RESIZE_READY 204 | resize_bar_location = [location] 205 | 206 | elif location[1] == -1: # top 207 | if dis.x <= gap: 208 | mouse_default_cursor_shape = CURSOR_HSIZE 209 | action = Actions.RESIZE_READY 210 | resize_bar_location = [location] 211 | 212 | else: 213 | if dis.x <= gap and dis.y <= gap: 214 | mouse_default_cursor_shape = CURSOR_FDIAGSIZE 215 | action = Actions.RESIZE_READY 216 | resize_bar_location = [ [-1, location[1]], [location[0],-1] ] 217 | return resize_bar_location 218 | 219 | #--------------------------------------------------------------------------------------------------- 220 | func set_top_bar_size(x_index:int, width:float): 221 | var location = [x_index, -1] 222 | var bar_rect = top_bar_rects[location] 223 | bar_rect.size.x = max(MIN_LENGTH, width) 224 | top_bar_rects[location] = bar_rect 225 | # 偏移后续的对象 226 | for i in range(x_index+1, cell_x_count): 227 | var offset_rect = top_bar_rects[[i, -1]] 228 | offset_rect.position.x = bar_rect.end.x+GAP 229 | top_bar_rects[[i, -1]] = offset_rect 230 | bar_rect = offset_rect 231 | control.custom_minimum_size = get_cell_rect([cell_x_count-1, cell_y_count-1]).end + Vector2(8, 8) 232 | 233 | #--------------------------------------------------------------------------------------------------- 234 | func set_side_bar_size(y_index:int, height:float): 235 | var location = [-1, y_index] 236 | var bar_rect = side_bar_rects[location] 237 | bar_rect.size.y = max(MIN_LENGTH, height) 238 | side_bar_rects[location] = bar_rect 239 | for i in range(y_index+1, cell_y_count): 240 | var offset_rect = side_bar_rects[[-1, i]] 241 | offset_rect.position.y = bar_rect.end.y+GAP 242 | side_bar_rects[[-1, i]] = offset_rect 243 | bar_rect = offset_rect 244 | control.custom_minimum_size = get_cell_rect([cell_x_count-1, cell_y_count-1]).end + Vector2(8, 8) 245 | 246 | 247 | #--------------------------------------------------------------------------------------------------- 248 | func get_hovered_bar() -> Array: 249 | # bar 250 | var mp := control.get_local_mouse_position() 251 | if mp.y <= TOP_BAR_HEIGHT: 252 | var x_start = false 253 | for location: Array in top_bar_rects: 254 | var rect = top_bar_rects[location] 255 | # Skip start 256 | if not x_start: 257 | if parent_rect.position.x > rect.end.x: 258 | continue 259 | x_start = true 260 | # Skip end 261 | if parent_rect.end.x < rect.position.x: 262 | break 263 | 264 | if rect.has_point(mp): 265 | return location 266 | 267 | if mp.x <= SIDE_BAR_WIDTH: 268 | var y_start = false 269 | for location: Array in side_bar_rects: 270 | var rect = side_bar_rects[location] 271 | # Skip start 272 | if not y_start: 273 | if parent_rect.position.y > rect.end.y: 274 | continue 275 | y_start = true 276 | 277 | # Skip end 278 | if parent_rect.end.y < rect.position.y: 279 | break 280 | 281 | if rect.has_point(mp): 282 | return location 283 | return [] 284 | 285 | #--------------------------------------------------------------------------------------------------- 286 | func get_hovered() -> Array: 287 | var hovered = get_hovered_bar() 288 | if hovered: 289 | return hovered 290 | var mp := control.get_local_mouse_position() 291 | # [x, y] 292 | var start = false 293 | for x in range(cell_x_count): 294 | for y in range(cell_y_count): 295 | var location = [x, y] 296 | var rect:Rect2 = get_cell_rect(location) 297 | ## Skip start 298 | if not start: 299 | if rect.end.x < parent_rect.position.x or rect.end.y < parent_rect.position.y : 300 | continue 301 | start = true 302 | if not parent_rect.intersects(rect): 303 | ## Skip ends 304 | if parent_rect.end.x < rect.position.x and parent_rect.end.y < rect.end.y : 305 | return [] 306 | continue 307 | if rect.has_point(mp): 308 | return location 309 | return [] 310 | 311 | #--------------------------------------------------------------------------------------------------- 312 | func generate_bars(): 313 | if cell_x_count <= 0 or cell_y_count <= 0: 314 | control.custom_minimum_size = Vector2.ZERO 315 | return 316 | top_bar_rects = {} 317 | side_bar_rects = {} 318 | var top_bar_rect := Rect2(SIDE_BAR_WIDTH, 0, MIN_LENGTH, TOP_BAR_HEIGHT) 319 | for x in range(cell_x_count): 320 | top_bar_rect.position = Vector2(SIDE_BAR_WIDTH + GAP + x*(MIN_LENGTH + GAP), 0) 321 | top_bar_rects[[x, -1]] = top_bar_rect 322 | 323 | var side_bar_rect := Rect2(0, TOP_BAR_HEIGHT, SIDE_BAR_WIDTH, MIN_LENGTH) 324 | for y in range(cell_y_count): 325 | side_bar_rect.position = Vector2(0, TOP_BAR_HEIGHT + GAP + y*(MIN_LENGTH + GAP)) 326 | side_bar_rects[[-1, y]] = side_bar_rect 327 | 328 | control.custom_minimum_size = get_cell_rect([cell_x_count-1, cell_y_count-1]).end + Vector2(8, 8) 329 | 330 | #--------------------------------------------------------------------------------------------------- 331 | func get_cell_rect(location:Array) -> Rect2: 332 | # 也会返回 bar rect 333 | var x = location[0] 334 | var y = location[1] 335 | if x == -1: 336 | return side_bar_rects[location] 337 | if y == -1: 338 | return top_bar_rects[location] 339 | var bar_x_rect = top_bar_rects[[x, -1]] 340 | var bar_y_rect = side_bar_rects[[-1, y]] 341 | return Rect2(bar_x_rect.position.x, bar_y_rect.position.y, bar_x_rect.size.x, bar_y_rect.size.y) 342 | 343 | #--------------------------------------------------------------------------------------------------- 344 | func check_select(): 345 | var shift_pressed := Input.is_key_pressed(KEY_SHIFT) 346 | var ctrl_pressed := Input.is_key_pressed(KEY_CTRL) 347 | if not shift_pressed and not ctrl_pressed: 348 | select_locations = [] 349 | if not hovered_location: 350 | return 351 | 352 | # 整行整列选择 353 | if hovered_location[0] == -1: # SIDE 354 | if ctrl_pressed: 355 | for x in range(cell_x_count): 356 | set_select([x, hovered_location[1]], false) 357 | else: 358 | for x in range(cell_x_count): 359 | set_select([x, hovered_location[1]], true) 360 | return 361 | elif hovered_location[1] == -1: # TOP 362 | if ctrl_pressed: 363 | for y in range(cell_y_count): 364 | set_select([hovered_location[0], y], false) 365 | else: 366 | for y in range(cell_y_count): 367 | set_select([hovered_location[0], y], true) 368 | return 369 | 370 | # 连选 371 | if ctrl_pressed: 372 | set_select(hovered_location, false) 373 | elif shift_pressed: 374 | if select_locations: 375 | var start_x = select_locations[-1][0] 376 | var start_y = select_locations[-1][1] 377 | if start_x == hovered_location[0]: 378 | var ran = abs(start_y - hovered_location[1]) 379 | var sig = sign(hovered_location[1]-start_y) 380 | for y in ran: 381 | var new_index = y*sig+start_y+sig 382 | set_select([start_x, new_index], true) 383 | 384 | elif start_y == hovered_location[1]: 385 | var ran = abs(start_x - hovered_location[0]) 386 | var sig = sign(hovered_location[0]-start_x) 387 | for x in ran: 388 | var new_index = x*sig+start_x+sig 389 | set_select([new_index, start_y], true) 390 | set_select(hovered_location, true) 391 | 392 | else: 393 | set_select(hovered_location, true) 394 | 395 | #--------------------------------------------------------------------------------------------------- 396 | func is_selected(location:Array): 397 | return location in select_locations 398 | 399 | #--------------------------------------------------------------------------------------------------- 400 | func set_select(location:Array, value:bool): 401 | if not value: 402 | select_locations.erase(location) 403 | elif value and select_locations.find(location) == -1: 404 | select_locations.append(location) 405 | 406 | #--------------------------------------------------------------------------------------------------- 407 | # [ THEME ] 408 | #--------------------------------------------------------------------------------------------------- 409 | func get_base_stylebox(type:int=0) -> StyleBoxFlat: 410 | var box := StyleBoxFlat.new() 411 | match type: 412 | 0: 413 | box.bg_color = Color.BLACK 414 | 1: 415 | box.draw_center = false 416 | box.border_color = Color.WEB_GRAY 417 | box.set_border_width_all(1) 418 | 2: 419 | box.draw_center = false 420 | box.border_color = Color.GREEN 421 | box.set_border_width_all(1) 422 | 3: # bar resize 423 | box.draw_center = false 424 | box.border_color = Color.WHITE 425 | box.set_border_width_all(1) 426 | 4: # SBOX_HOVERED_INDEX 427 | box.bg_color = Color.WHITE_SMOKE 428 | box.corner_radius_top_left = 4 429 | box.corner_radius_top_right = 4 430 | 431 | 432 | return box 433 | 434 | func get_base_font() -> FontVariation: 435 | var font := FontVariation.new() 436 | font.set_base_font(INTER_VARIABLE_FONT_SLNT_WGHT) 437 | return font 438 | 439 | 440 | #--------------------------------------------------------------------------------------------------- 441 | # [ CANVAS ] 442 | #--------------------------------------------------------------------------------------------------- 443 | func draw_cell_grid(): 444 | #print("drawing") 445 | rs.canvas_item_clear(base_rid) 446 | if cell_x_count <= 0 or cell_y_count <= 0: 447 | return 448 | draw_bar() 449 | draw_cells() 450 | 451 | #--------------------------------------------------------------------------------------------------- 452 | func draw_bar(): 453 | #SBOX_BG.draw(base_rid, Rect2(0,0,SIDE_BAR_WIDTH, TOP_BAR_HEIGHT)) 454 | rs.canvas_item_add_rect(base_rid, Rect2(0,0,SIDE_BAR_WIDTH, TOP_BAR_HEIGHT), Color.BLACK) 455 | 456 | var ascent = FONT.get_ascent() 457 | 458 | var x_start = false 459 | for x in range(cell_x_count): 460 | var rect = top_bar_rects[[x, -1]] 461 | # Skip start 462 | if not x_start: 463 | if parent_rect.position.x > rect.end.x: 464 | continue 465 | x_start = true 466 | # Skip end 467 | if parent_rect.end.x < rect.position.x: 468 | break 469 | 470 | rs.canvas_item_add_rect(base_rid, rect, Color.BLACK) 471 | #SBOX_BG.draw(base_rid, rect) 472 | var text = str(x+1) 473 | var font_size = FONT.get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT) 474 | var offset = (rect.size-font_size)*0.5 + Vector2(0, ascent) 475 | FONT.draw_string(base_rid, rect.position + offset, text) 476 | 477 | 478 | var y_start = false 479 | for y in range(cell_y_count): 480 | var rect = side_bar_rects[[-1, y]] 481 | 482 | # Skip start 483 | if not y_start: 484 | if parent_rect.position.y > rect.end.y: 485 | continue 486 | y_start = true 487 | # Skip end 488 | if parent_rect.end.y < rect.position.y: 489 | break 490 | #SBOX_BG.draw(base_rid, rect) 491 | rs.canvas_item_add_rect(base_rid, rect, Color.BLACK) 492 | var text = str(y+1) 493 | var font_size = FONT.get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT) 494 | var offset = (rect.size-font_size)*0.5 + Vector2(0, ascent) 495 | FONT.draw_string(base_rid, rect.position + offset, text) 496 | 497 | #--------------------------------------------------------------------------------------------------- 498 | func draw_cells(): 499 | var start = false 500 | for x in range(cell_x_count): 501 | for y in range(cell_y_count): 502 | var location = [x, y] 503 | var rect:Rect2 = get_cell_rect(location) 504 | 505 | ## Skip start 506 | if not start: 507 | if rect.end.x < parent_rect.position.x or rect.end.y < parent_rect.position.y : 508 | continue 509 | start = true 510 | if not parent_rect.intersects(rect): 511 | ## Skip ends 512 | if parent_rect.end.x < rect.position.x and parent_rect.end.y < rect.end.y : 513 | return 514 | continue 515 | 516 | #SBOX_BG.draw(base_rid, rect) 517 | rs.canvas_item_add_rect(base_rid, rect, Color("060606")) 518 | 519 | #--------------------------------------------------------------------------------------------------- 520 | func draw_items(): 521 | rs.canvas_item_clear(items_rid) 522 | var gap = 8 523 | var font_size = 16 524 | var ascent = FONT.get_ascent(font_size) 525 | var text_offset = Vector2(gap, ascent+gap) 526 | 527 | var start = false 528 | for location:Array in cell_items: 529 | var item = cell_items[location] 530 | var rect = get_cell_rect(location) 531 | 532 | ## Skip start 533 | if not start: 534 | if rect.end.x < parent_rect.position.x or rect.end.y < parent_rect.position.y : 535 | continue 536 | start = true 537 | if not parent_rect.intersects(rect): 538 | ## Skip ends 539 | if parent_rect.end.x < rect.position.x and parent_rect.end.y < rect.end.y : 540 | break 541 | continue 542 | if item is Texture2D: 543 | var texture_aspect = item.get_size().aspect() 544 | var rect_aspect = rect.size.aspect() 545 | var old_size = rect.size 546 | if texture_aspect < rect_aspect: 547 | rect.size.x = rect.size.y*texture_aspect 548 | rect.position.x += (old_size-rect.size).x*0.5 549 | else: 550 | rect.size.y = rect.size.x/texture_aspect 551 | rect.position.y += (old_size-rect.size).y*0.5 552 | rs.canvas_item_add_texture_rect(items_rid, rect, item.get_rid()) 553 | 554 | elif item is String: 555 | var max_lines = int((rect.size.y-gap*2) / FONT.get_height(font_size)) 556 | var width = rect.size.x-gap*2 557 | FONT.draw_multiline_string(items_rid, rect.position + text_offset, item, 0, width, font_size, max_lines, Color.WHITE_SMOKE, TextServer.BREAK_GRAPHEME_BOUND) 558 | 559 | #--------------------------------------------------------------------------------------------------- 560 | func draw_indicator(): 561 | rs.canvas_item_clear(indicator_rid) 562 | if hovered_location: 563 | var rect:Rect2 = get_cell_rect(hovered_location) 564 | SBOX_HOVERED.draw(indicator_rid, rect) 565 | if hovered_location[0] != -1 and hovered_location[1] != -1: 566 | var font_size = 16 567 | var text= str(hovered_location[0]+1)+" , " + str(hovered_location[1]+1) 568 | var ascent = FONT.get_ascent(font_size) 569 | var text_size = FONT.get_string_size(text, HORIZONTAL_ALIGNMENT_LEFT, rect.size.x, font_size) 570 | var text_rect := Rect2(rect.position.x, rect.position.y-text_size.y, text_size.x+8, text_size.y) 571 | var offset = (text_rect.size-text_size)*0.5 + Vector2(0, ascent) 572 | SBOX_HOVERED_INDEX.draw(indicator_rid, text_rect) 573 | FONT.draw_string(indicator_rid, text_rect.position + offset, text, 0, rect.size.x,font_size,Color.BLACK) 574 | 575 | if select_locations: 576 | for location:Array in select_locations: 577 | var rect:Rect2 = get_cell_rect(location) 578 | SBOX_SELECT.draw(indicator_rid, rect) 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | -------------------------------------------------------------------------------- /components/custom_window_bar/cusBBE6.tmp: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=6 format=3 uid="uid://b3kobiipq2jbo"] 2 | 3 | [ext_resource type="Script" path="res://components/custom_window_bar/custom_window_bar.gd" id="1_5unlh"] 4 | [ext_resource type="Script" path="res://components/custom_window_bar/window_scaler_component.gd" id="2_4gkye"] 5 | [ext_resource type="Script" path="res://components/custom_window_bar/window_state_component.gd" id="2_hnrtg"] 6 | [ext_resource type="Script" path="res://components/custom_window_bar/window_drag_component.gd" id="2_lons0"] 7 | [ext_resource type="Texture2D" uid="uid://cv3lk1pbm7kla" path="res://resource/icons/Boghma.png" id="3_eh4sk"] 8 | 9 | [node name="CustomWindowBar" type="PanelContainer"] 10 | anchors_preset = 10 11 | anchor_right = 1.0 12 | offset_bottom = 64.0 13 | grow_horizontal = 2 14 | script = ExtResource("1_5unlh") 15 | 16 | [node name="WindowStateComponent" type="Node" parent="."] 17 | unique_name_in_owner = true 18 | script = ExtResource("2_hnrtg") 19 | 20 | [node name="WindowDragComponent" type="Node" parent="."] 21 | unique_name_in_owner = true 22 | script = ExtResource("2_lons0") 23 | 24 | [node name="WindowScalerComponent" type="Node" parent="."] 25 | unique_name_in_owner = true 26 | script = ExtResource("2_4gkye") 27 | 28 | [node name="HBoxContainer" type="HBoxContainer" parent="."] 29 | layout_mode = 2 30 | 31 | [node name="MarginContainer" type="MarginContainer" parent="HBoxContainer"] 32 | layout_mode = 2 33 | theme_override_constants/margin_left = 16 34 | theme_override_constants/margin_top = 16 35 | theme_override_constants/margin_right = 8 36 | theme_override_constants/margin_bottom = 16 37 | 38 | [node name="TextureRectWindowIcon" type="TextureRect" parent="HBoxContainer/MarginContainer"] 39 | unique_name_in_owner = true 40 | custom_minimum_size = Vector2(32, 32) 41 | layout_mode = 2 42 | texture = ExtResource("3_eh4sk") 43 | expand_mode = 1 44 | 45 | [node name="LabelWindowTitle" type="Label" parent="HBoxContainer"] 46 | unique_name_in_owner = true 47 | layout_mode = 2 48 | size_flags_horizontal = 3 49 | text = "Boghma" 50 | clip_text = true 51 | 52 | [node name="BtnMinimizeWindow" type="Button" parent="HBoxContainer"] 53 | unique_name_in_owner = true 54 | custom_minimum_size = Vector2(64, 48) 55 | layout_mode = 2 56 | text = "---" 57 | 58 | [node name="BtnMaxsimizeWindow" type="Button" parent="HBoxContainer"] 59 | unique_name_in_owner = true 60 | custom_minimum_size = Vector2(64, 48) 61 | layout_mode = 2 62 | text = "O" 63 | 64 | [node name="BtnCloseWindow" type="Button" parent="HBoxContainer"] 65 | unique_name_in_owner = true 66 | custom_minimum_size = Vector2(64, 48) 67 | layout_mode = 2 68 | text = "X" 69 | -------------------------------------------------------------------------------- /components/custom_window_bar/custom_window_bar.gd: -------------------------------------------------------------------------------- 1 | extends PanelContainer 2 | """ 3 | ## NOTE: 4 | 1.this three setting must be true if you want a transparent background! 5 | ProjectSettings.set("display/window/size/borderless", true) 6 | ProjectSettings.set("display/window/size/transparent", true) 7 | ProjectSettings.set("rendering/viewport/transparent_background", true) 8 | 9 | 2.top level of container grow direction needs to be Right and Bottom 10 | """ 11 | 12 | @export var window_min_size:= Vector2i(300,100): 13 | set(value): 14 | window_min_size = value 15 | if is_node_ready(): 16 | window_resize_component.min_size = window_min_size 17 | 18 | @onready var texture_rect_window_icon = %TextureRectWindowIcon 19 | @onready var label_window_title = %LabelWindowTitle 20 | @onready var btn_minimize_window = %BtnMinimizeWindow 21 | @onready var btn_maxsimize_window = %BtnMaxsimizeWindow 22 | @onready var btn_close_window = %BtnCloseWindow 23 | 24 | @onready var window_state_component = %WindowStateComponent 25 | @onready var window_drag_component = %WindowDragComponent 26 | @onready var window_resize_component = %WindowResizeComponent 27 | 28 | func _ready(): 29 | window_min_size = window_min_size 30 | btn_minimize_window.pressed.connect(window_state_component.set_minimized) 31 | btn_maxsimize_window.pressed.connect(window_state_component.toggle_maxsimized) 32 | btn_close_window.pressed.connect(window_state_component.quit) 33 | 34 | window_drag_component.drag_started.connect(func(): window_resize_component.activate = false ) 35 | window_drag_component.drag_stoped.connect(func(): window_resize_component.activate = true ) 36 | 37 | func _process(delta): 38 | var is_resize = window_resize_component.is_waiting_resize() or window_resize_component.is_resizing() 39 | btn_minimize_window.disabled = is_resize 40 | btn_maxsimize_window.disabled = is_resize 41 | btn_close_window.disabled = is_resize 42 | 43 | func _input(event): 44 | if event is InputEventMouseButton: 45 | if event.is_pressed() and event.button_index == MOUSE_BUTTON_LEFT: 46 | if window_resize_component.is_waiting_resize(): 47 | window_resize_component.start_resize() 48 | get_viewport().set_input_as_handled() 49 | elif not event.is_pressed() and event.button_index == MOUSE_BUTTON_LEFT: 50 | if window_resize_component.is_resizing(): 51 | window_resize_component.stop_resize() 52 | get_viewport().set_input_as_handled() 53 | 54 | if event is InputEventMouseMotion: 55 | if event.button_mask == MOUSE_BUTTON_MASK_LEFT: 56 | if window_resize_component.is_resizing(): 57 | get_viewport().set_input_as_handled() 58 | 59 | func _notification(what): 60 | if what == NOTIFICATION_WM_WINDOW_FOCUS_IN: 61 | pass 62 | elif what == NOTIFICATION_WM_WINDOW_FOCUS_OUT: 63 | if window_resize_component.is_resizing(): 64 | window_resize_component.stop_resize() 65 | if window_drag_component.is_dragging(): 66 | window_drag_component.stop_drag() 67 | 68 | func _gui_input(event): 69 | if event is InputEventMouseButton: 70 | if event.button_index == MOUSE_BUTTON_LEFT: 71 | if event.is_pressed(): 72 | pass 73 | elif window_drag_component.is_dragging(): 74 | window_drag_component.stop_drag() 75 | 76 | if event is InputEventMouseMotion: 77 | if event.button_mask == MOUSE_BUTTON_MASK_LEFT: 78 | if window_state_component.is_maxsimized(): 79 | # 全屏状态下拖拽会缩小窗口 80 | window_state_component.set_windowed() 81 | var win_size = DisplayServer.window_get_size()*0.5 82 | DisplayServer.window_set_position(DisplayServer.mouse_get_position()-Vector2i(win_size.x,20)) 83 | if not window_drag_component.is_dragging(): 84 | window_drag_component.start_drag() 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /components/custom_window_bar/custom_window_bar.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=12 format=3 uid="uid://b3kobiipq2jbo"] 2 | 3 | [ext_resource type="Script" path="res://components/custom_window_bar/custom_window_bar.gd" id="1_5unlh"] 4 | [ext_resource type="Script" path="res://components/custom_window_bar/window_resize_component.gd" id="2_4gkye"] 5 | [ext_resource type="Script" path="res://components/custom_window_bar/window_state_component.gd" id="2_hnrtg"] 6 | [ext_resource type="Script" path="res://components/custom_window_bar/window_drag_component.gd" id="2_lons0"] 7 | [ext_resource type="Texture2D" uid="uid://cv3lk1pbm7kla" path="res://resource/icons/Boghma.png" id="3_eh4sk"] 8 | 9 | [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_irl2v"] 10 | 11 | [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_o88xo"] 12 | 13 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_sclpu"] 14 | draw_center = false 15 | border_width_bottom = 4 16 | border_color = Color(0.303558, 0.552087, 0.792969, 1) 17 | 18 | [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_calml"] 19 | 20 | [sub_resource type="Theme" id="Theme_nu6y7"] 21 | Button/colors/font_color = Color(0.87451, 0.87451, 0.87451, 1) 22 | Button/colors/font_disabled_color = Color(0.87451, 0.87451, 0.87451, 1) 23 | Button/styles/disabled = SubResource("StyleBoxEmpty_irl2v") 24 | Button/styles/focus = SubResource("StyleBoxEmpty_o88xo") 25 | Button/styles/hover = SubResource("StyleBoxFlat_sclpu") 26 | Button/styles/normal = SubResource("StyleBoxEmpty_calml") 27 | 28 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ptbxd"] 29 | bg_color = Color(0.0980392, 0.0980392, 0.0980392, 1) 30 | 31 | [node name="CustomWindowBar" type="PanelContainer"] 32 | clip_contents = true 33 | anchors_preset = 10 34 | anchor_right = 1.0 35 | offset_bottom = 64.0 36 | grow_horizontal = 2 37 | theme = SubResource("Theme_nu6y7") 38 | theme_override_styles/panel = SubResource("StyleBoxFlat_ptbxd") 39 | script = ExtResource("1_5unlh") 40 | 41 | [node name="WindowResizeComponent" type="Node" parent="."] 42 | unique_name_in_owner = true 43 | script = ExtResource("2_4gkye") 44 | min_size = Vector2i(300, 100) 45 | 46 | [node name="WindowStateComponent" type="Node" parent="."] 47 | unique_name_in_owner = true 48 | script = ExtResource("2_hnrtg") 49 | 50 | [node name="WindowDragComponent" type="Node" parent="."] 51 | unique_name_in_owner = true 52 | script = ExtResource("2_lons0") 53 | 54 | [node name="HBoxContainer" type="HBoxContainer" parent="."] 55 | layout_mode = 2 56 | 57 | [node name="MarginContainer" type="MarginContainer" parent="HBoxContainer"] 58 | layout_mode = 2 59 | theme_override_constants/margin_left = 16 60 | theme_override_constants/margin_top = 16 61 | theme_override_constants/margin_right = 8 62 | theme_override_constants/margin_bottom = 16 63 | 64 | [node name="TextureRectWindowIcon" type="TextureRect" parent="HBoxContainer/MarginContainer"] 65 | unique_name_in_owner = true 66 | custom_minimum_size = Vector2(32, 32) 67 | layout_mode = 2 68 | texture = ExtResource("3_eh4sk") 69 | expand_mode = 1 70 | 71 | [node name="LabelWindowTitle" type="Label" parent="HBoxContainer"] 72 | unique_name_in_owner = true 73 | layout_mode = 2 74 | size_flags_horizontal = 3 75 | text = "Boghma" 76 | clip_text = true 77 | 78 | [node name="BtnMinimizeWindow" type="Button" parent="HBoxContainer"] 79 | unique_name_in_owner = true 80 | custom_minimum_size = Vector2(64, 48) 81 | layout_mode = 2 82 | text = "---" 83 | 84 | [node name="BtnMaxsimizeWindow" type="Button" parent="HBoxContainer"] 85 | unique_name_in_owner = true 86 | custom_minimum_size = Vector2(64, 48) 87 | layout_mode = 2 88 | text = "O" 89 | 90 | [node name="BtnCloseWindow" type="Button" parent="HBoxContainer"] 91 | unique_name_in_owner = true 92 | custom_minimum_size = Vector2(64, 48) 93 | layout_mode = 2 94 | text = "X" 95 | -------------------------------------------------------------------------------- /components/custom_window_bar/example/cwb_application_example.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=10 format=3 uid="uid://dcae4kyb4oltp"] 2 | 3 | [ext_resource type="Texture2D" uid="uid://baguolgtgf26d" path="res://resource/icons/godot.png" id="2_1s4ce"] 4 | [ext_resource type="Shader" uid="uid://corhjembtpeld" path="res://resource/shader/ms_fill.tres" id="2_lh0wa"] 5 | [ext_resource type="PackedScene" uid="uid://b3kobiipq2jbo" path="res://components/custom_window_bar/custom_window_bar.tscn" id="2_ujjva"] 6 | 7 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_s61cp"] 8 | bg_color = Color(0.196078, 0.196078, 0.196078, 1) 9 | border_width_left = 2 10 | border_width_top = 2 11 | border_width_right = 2 12 | border_width_bottom = 2 13 | border_color = Color(0.0392157, 0.0392157, 0.0392157, 1) 14 | border_blend = true 15 | corner_radius_top_left = 16 16 | corner_radius_top_right = 16 17 | corner_radius_bottom_right = 16 18 | corner_radius_bottom_left = 16 19 | 20 | [sub_resource type="ShaderMaterial" id="ShaderMaterial_yvb81"] 21 | shader = ExtResource("2_lh0wa") 22 | shader_parameter/Fill = Color(0.301961, 0.552941, 0.792157, 1) 23 | 24 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_5qlcl"] 25 | content_margin_left = 32.0 26 | content_margin_right = 32.0 27 | bg_color = Color(0.113725, 0.113725, 0.113725, 1) 28 | corner_radius_top_left = 8 29 | corner_radius_top_right = 8 30 | corner_radius_bottom_right = 8 31 | corner_radius_bottom_left = 8 32 | 33 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_e47jf"] 34 | content_margin_left = 32.0 35 | content_margin_right = 32.0 36 | bg_color = Color(0.113725, 0.113725, 0.113725, 1) 37 | border_width_left = 2 38 | border_width_top = 2 39 | border_width_right = 2 40 | border_width_bottom = 2 41 | border_color = Color(0.8, 0.8, 0.8, 0.27451) 42 | corner_radius_top_left = 8 43 | corner_radius_top_right = 8 44 | corner_radius_bottom_right = 8 45 | corner_radius_bottom_left = 8 46 | 47 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_gso66"] 48 | content_margin_left = 32.0 49 | content_margin_right = 32.0 50 | bg_color = Color(0.301961, 0.552941, 0.792157, 1) 51 | corner_radius_top_left = 8 52 | corner_radius_top_right = 8 53 | corner_radius_bottom_right = 8 54 | corner_radius_bottom_left = 8 55 | 56 | [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_kbyei"] 57 | 58 | [node name="Application" type="PanelContainer"] 59 | clip_children = 2 60 | clip_contents = true 61 | anchors_preset = 15 62 | anchor_right = 1.0 63 | anchor_bottom = 1.0 64 | grow_horizontal = 2 65 | grow_vertical = 2 66 | theme_override_styles/panel = SubResource("StyleBoxFlat_s61cp") 67 | 68 | [node name="VSplitContainer" type="VSplitContainer" parent="."] 69 | layout_mode = 2 70 | split_offset = -160 71 | collapsed = true 72 | dragger_visibility = 2 73 | 74 | [node name="CustomWindowBar" parent="VSplitContainer" instance=ExtResource("2_ujjva")] 75 | layout_mode = 2 76 | window_min_size = Vector2i(500, 500) 77 | 78 | [node name="Main" type="Control" parent="VSplitContainer"] 79 | clip_contents = true 80 | layout_mode = 2 81 | 82 | [node name="MarginContainer" type="MarginContainer" parent="VSplitContainer/Main"] 83 | layout_mode = 1 84 | anchors_preset = 15 85 | anchor_right = 1.0 86 | anchor_bottom = 1.0 87 | grow_horizontal = 2 88 | grow_vertical = 2 89 | theme_override_constants/margin_left = 16 90 | theme_override_constants/margin_top = 16 91 | theme_override_constants/margin_right = 16 92 | theme_override_constants/margin_bottom = 16 93 | 94 | [node name="VBoxContainer" type="VBoxContainer" parent="VSplitContainer/Main/MarginContainer"] 95 | layout_mode = 2 96 | theme_override_constants/separation = 0 97 | 98 | [node name="CenterContainer" type="CenterContainer" parent="VSplitContainer/Main/MarginContainer/VBoxContainer"] 99 | layout_mode = 2 100 | size_flags_vertical = 3 101 | 102 | [node name="TextureRect" type="TextureRect" parent="VSplitContainer/Main/MarginContainer/VBoxContainer/CenterContainer"] 103 | material = SubResource("ShaderMaterial_yvb81") 104 | custom_minimum_size = Vector2(200, 200) 105 | layout_mode = 2 106 | texture = ExtResource("2_1s4ce") 107 | expand_mode = 1 108 | stretch_mode = 5 109 | 110 | [node name="Button" type="Button" parent="VSplitContainer/Main/MarginContainer/VBoxContainer"] 111 | custom_minimum_size = Vector2(0, 52) 112 | layout_mode = 2 113 | size_flags_horizontal = 4 114 | theme_override_font_sizes/font_size = 16 115 | theme_override_styles/normal = SubResource("StyleBoxFlat_5qlcl") 116 | theme_override_styles/hover = SubResource("StyleBoxFlat_e47jf") 117 | theme_override_styles/pressed = SubResource("StyleBoxFlat_gso66") 118 | theme_override_styles/focus = SubResource("StyleBoxEmpty_kbyei") 119 | text = "CLICK ME!" 120 | -------------------------------------------------------------------------------- /components/custom_window_bar/window_drag_component.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | signal drag_started 4 | signal drag_stoped 5 | 6 | @export var window_id:int = 0 7 | 8 | var _offset_position:Vector2i 9 | 10 | func _ready(): 11 | stop_drag() 12 | 13 | func _process(delta): 14 | DisplayServer.window_set_position(DisplayServer.mouse_get_position()+_offset_position, window_id) 15 | 16 | ## Interface 17 | func start_drag(): 18 | set_process(true) 19 | _offset_position = DisplayServer.window_get_position(window_id) -DisplayServer.mouse_get_position() 20 | drag_started.emit() 21 | 22 | func stop_drag(): 23 | set_process(false) 24 | _offset_position = Vector2.ZERO 25 | drag_stoped.emit() 26 | 27 | func is_dragging(): 28 | return is_processing() 29 | -------------------------------------------------------------------------------- /components/custom_window_bar/window_resize_component.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | signal cursor_index_changed(index) 4 | 5 | @export var window_id:int = 0 ## Window index 6 | @export var activate:bool = true: ## Set false if you want to stop process 7 | set(value): 8 | activate = value 9 | set_process(value) 10 | @export var min_size := Vector2i(260, 100) ## Min window size 11 | @export var detect_state_gap :int = 2 ## distance (pixcel) to window border on detect state 12 | @export var other_state_gap :int = 16 ## distance (pixcel) to window border on other state 13 | @export var change_cursor := true ## set false if you don't want to change cursor 14 | @export var only_change_on_windowed_mode:= true ## set false if you want to change scale on FULLSCREEN mode 15 | 16 | const CURSOR_LIST = [ DisplayServer.CURSOR_ARROW, 17 | DisplayServer.CURSOR_FDIAGSIZE, # 1 18 | DisplayServer.CURSOR_VSIZE, 19 | DisplayServer.CURSOR_BDIAGSIZE, 20 | DisplayServer.CURSOR_HSIZE, 21 | DisplayServer.CURSOR_ARROW, #5 22 | DisplayServer.CURSOR_HSIZE, 23 | DisplayServer.CURSOR_BDIAGSIZE, # 7 24 | DisplayServer.CURSOR_VSIZE, 25 | DisplayServer.CURSOR_FDIAGSIZE, 26 | ] 27 | enum State {Detect, Wait, Resize} 28 | var state = State.Detect 29 | 30 | var _start_window_rect:Rect2i 31 | var _resize_index :int = 0 32 | 33 | func _ready(): 34 | activate = activate 35 | 36 | func _process(delta): 37 | if only_change_on_windowed_mode and DisplayServer.window_get_mode(window_id) != DisplayServer.WINDOW_MODE_WINDOWED: 38 | return 39 | var _mp = DisplayServer.mouse_get_position() 40 | var _window_rect = get_window_rect(window_id) 41 | var gap = detect_state_gap if state == State.Detect else other_state_gap 42 | var _inside_rect = _window_rect.grow(-gap) 43 | 44 | if state != State.Resize: 45 | _resize_index = get_grid_index(_window_rect, _mp, gap) 46 | cursor_index_changed.emit(_resize_index) 47 | if change_cursor: 48 | DisplayServer.cursor_set_shape(CURSOR_LIST[_resize_index]) 49 | 50 | match state: 51 | State.Detect: 52 | if _window_rect.has_point(_mp) and not _inside_rect.has_point(_mp): 53 | state = State.Wait 54 | State.Wait: 55 | if _window_rect.has_point(_mp) and not _inside_rect.has_point(_mp): 56 | _start_window_rect = _window_rect 57 | else: 58 | state = State.Detect 59 | State.Resize: 60 | resize_window(_start_window_rect, _mp, _resize_index, min_size) 61 | 62 | ## Interface 63 | func is_waiting_resize(): 64 | return state == State.Wait 65 | 66 | func is_resizing(): 67 | return state == State.Resize 68 | 69 | func start_resize(): 70 | if state == State.Wait: 71 | state = State.Resize 72 | 73 | func stop_resize(): 74 | if state == State.Resize: 75 | state = State.Detect 76 | 77 | func resize_window(start_rect:Rect2i, point:Vector2i, index:int, min_size:Vector2, window_id:int=0): 78 | var rect = Rect2i(resize_rect(start_rect, point, index, min_size)) 79 | DisplayServer.window_set_position(rect.position, window_id) 80 | DisplayServer.window_set_size(rect.size, window_id) 81 | 82 | ## Statics 83 | static func get_grid_index(rect:Rect2, point:Vector2, gap:float): 84 | var local_mp = point-rect.position 85 | var w = rect.size.x 86 | var h = rect.size.y 87 | var x = local_mp.x 88 | var y = local_mp.y 89 | var index = 0 90 | if y PackedVector2Array: 38 | var delta = PI*0.5/count 39 | var round_points := PackedVector2Array() 40 | for i in range(count+1): 41 | var ri = count-i 42 | var pos = Vector2(radius * cos(delta*i+ PI), radius * sin(delta*i+ PI)) 43 | round_points.append(pos) 44 | return round_points 45 | 46 | static func get_round_rect(rect:Rect2, radius:int, round_count:int=16) -> PackedVector2Array: 47 | var points := PackedVector2Array() 48 | points.append(Vector2.ZERO) 49 | points.append(Vector2(rect.size.x, 0)) 50 | points.append(rect.size) 51 | points.append(Vector2(0, rect.size.y)) 52 | # 53 | var round_points = _get_corner_round_points(radius, round_count) 54 | 55 | # bevel 56 | for i in range(4): 57 | var index = 3-i 58 | var prev = points[index-1] 59 | var curr = points[index] 60 | var next = points[(index+1)%points.size()] 61 | var v_prev = (prev-curr).normalized()*radius 62 | var v_next = (next-curr).normalized()*radius 63 | points[index] = curr+v_prev 64 | 65 | var offset_matrix = Transform2D().rotated(PI*0.5*index).translated(curr+v_prev+v_next) 66 | var rps :PackedVector2Array = offset_matrix*round_points 67 | rps.remove_at(0) 68 | for pindex in rps.size(): 69 | var rev_i = rps.size()-1-pindex 70 | points.insert(index+1, rps[rev_i].round()) 71 | points.append(points[0]) 72 | return points 73 | 74 | static func polyline_to_dash(points:PackedVector2Array, step:float, skip_step:float, sub_step_count:int=8) -> Array[PackedVector2Array]: 75 | var curve = Curve2D.new() 76 | for p in points: 77 | curve.add_point(p) 78 | var lenth = curve.get_baked_length() 79 | var dash_lines :Array[PackedVector2Array]= [] 80 | var total = 0 81 | var sub_step = step/sub_step_count 82 | 83 | # NOTE: 补偿尾端的一段距离到整个长度 84 | var seg = step + skip_step 85 | var count = round(lenth/seg) 86 | step = (lenth/count)*(step/seg) 87 | skip_step = (lenth/count)*(skip_step/seg) 88 | while true: 89 | if total >= lenth: 90 | break 91 | var end = total+step 92 | var temp := PackedVector2Array() 93 | for i in range(sub_step_count): 94 | temp.append(curve.sample_baked(total+i*sub_step)) 95 | dash_lines.append(temp) 96 | total = end+skip_step 97 | return dash_lines 98 | 99 | -------------------------------------------------------------------------------- /components/draggable_card_component/card/base_draggable_card.gd: -------------------------------------------------------------------------------- 1 | class_name BaseDragableCard extends PanelContainer 2 | 3 | signal drag_started 4 | signal drag_stoped 5 | 6 | var dragable := false 7 | 8 | ## Interface 9 | func start_drag(): 10 | dragable = true 11 | modulate.a = 0.9 12 | drag_started.emit() 13 | 14 | func stop_drag(): 15 | dragable = false 16 | modulate.a = 1 17 | drag_stoped.emit() 18 | 19 | func is_dragable(): 20 | return dragable 21 | 22 | -------------------------------------------------------------------------------- /components/draggable_card_component/card/base_draggable_card.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://1kesytt30cu1"] 2 | 3 | [ext_resource type="Script" path="res://components/draggable_card_component/card/base_draggable_card.gd" id="1_wskag"] 4 | 5 | [node name="BaseDraggableCard" type="PanelContainer"] 6 | offset_right = 570.0 7 | offset_bottom = 84.0 8 | script = ExtResource("1_wskag") 9 | -------------------------------------------------------------------------------- /components/draggable_card_component/card/place_holder_panel.gd: -------------------------------------------------------------------------------- 1 | class_name PlaceHolderPanel extends Panel 2 | 3 | var active := false 4 | 5 | var tween:Tween 6 | func change_size(value:Vector2, duration:float): 7 | if tween: 8 | tween.kill() 9 | tween = get_tree().create_tween() 10 | tween.set_ease(Tween.EASE_IN_OUT).set_trans(Tween.TRANS_CUBIC) 11 | tween.tween_property(self, "custom_minimum_size", value, duration) 12 | 13 | -------------------------------------------------------------------------------- /components/draggable_card_component/card/place_holder_panel.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://bg8fp2m6l85w0"] 2 | 3 | [ext_resource type="Script" path="res://components/draggable_card_component/card/place_holder_panel.gd" id="1_6o7yy"] 4 | 5 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_mpipx"] 6 | bg_color = Color(0.6, 0.6, 0.6, 0.490196) 7 | draw_center = false 8 | border_width_left = 4 9 | border_width_top = 4 10 | border_width_right = 4 11 | border_width_bottom = 4 12 | border_color = Color(0.839216, 0.694118, 0.415686, 1) 13 | corner_radius_top_left = 10 14 | corner_radius_top_right = 10 15 | corner_radius_bottom_right = 10 16 | corner_radius_bottom_left = 10 17 | shadow_color = Color(1, 0.972549, 0.929412, 1) 18 | 19 | [node name="PlaceHolderPanel" type="Panel"] 20 | custom_minimum_size = Vector2(200, 4) 21 | anchors_preset = 15 22 | anchor_right = 1.0 23 | anchor_bottom = 1.0 24 | offset_right = -283.0 25 | offset_bottom = -1163.0 26 | grow_horizontal = 2 27 | grow_vertical = 2 28 | size_flags_horizontal = 4 29 | theme_override_styles/panel = SubResource("StyleBoxFlat_mpipx") 30 | script = ExtResource("1_6o7yy") 31 | -------------------------------------------------------------------------------- /components/draggable_card_component/card/shadow_panel.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://kvt4c6h81b5i"] 2 | 3 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_mmorg"] 4 | bg_color = Color(0.6, 0.6, 0.6, 0) 5 | shadow_size = 10 6 | shadow_offset = Vector2(10, 10) 7 | 8 | [node name="ShadowPanel" type="Panel"] 9 | offset_right = 40.0 10 | offset_bottom = 40.0 11 | theme_override_styles/panel = SubResource("StyleBoxFlat_mmorg") 12 | -------------------------------------------------------------------------------- /components/draggable_card_component/draggable_card_component.gd: -------------------------------------------------------------------------------- 1 | extends VBoxContainer 2 | 3 | 4 | @export var PLACE_HOLDER_PACKED_SCENE:PackedScene 5 | @export var place_holder_min_size:=Vector2(200,4) 6 | @export var place_holder_duration :float = 0.2 7 | @export var _shadow_panel_packed_scene:PackedScene 8 | 9 | var _draged_card:BaseDragableCard 10 | var _drag_offset := Vector2.ZERO 11 | var _previous_index :int 12 | var _shadow_panel:Panel 13 | 14 | func _ready(): 15 | clear_cards() 16 | 17 | func _process(delta): 18 | _draging() 19 | 20 | func _input(event): 21 | if event is InputEventMouseButton: 22 | if not event.is_pressed() and event.button_index == MOUSE_BUTTON_LEFT: 23 | _stop_drag() 24 | 25 | ## Interface 26 | func clear_cards(): 27 | for child in get_children(): 28 | remove_card(child) 29 | 30 | func add_card(value:BaseDragableCard): 31 | if value not in get_children(): 32 | add_child(value) 33 | var call_start = _start_drag.bind(value) 34 | if not value.drag_started.is_connected(call_start): 35 | value.drag_started.connect(call_start) 36 | if not value.drag_stoped.is_connected(_stop_drag): 37 | value.drag_stoped.connect(_stop_drag) 38 | 39 | func remove_card(value:BaseDragableCard): 40 | if value in get_children(): 41 | remove_child(value) 42 | 43 | func get_cards(): 44 | return get_children().filter(func(x): return x is BaseDragableCard) 45 | 46 | ## Utils 47 | func _remove_all_place_holder(): 48 | for child in get_children(): 49 | if child is PlaceHolderPanel: 50 | remove_child(child) 51 | child.queue_free() 52 | 53 | func _add_place_holder(): 54 | _remove_all_place_holder() 55 | for index in get_child_count()+1: 56 | var place_holder = PLACE_HOLDER_PACKED_SCENE.instantiate() 57 | add_child(place_holder) 58 | move_child(place_holder, index*2) 59 | if index == _previous_index: 60 | place_holder.custom_minimum_size = _draged_card.size*0.8 61 | else: 62 | place_holder.custom_minimum_size = place_holder_min_size 63 | 64 | func _get_place_holders(): 65 | return get_children().filter(func(x): return x is PlaceHolderPanel) 66 | 67 | func _get_active_holder_index(): 68 | var actives = _get_place_holders().filter(func(x): return x.active) 69 | if actives: 70 | return actives[0].get_index()/2 71 | 72 | func _auto_change_place_holder_size(): 73 | if not _draged_card: 74 | return 75 | var mp = get_global_mouse_position() 76 | var height = _draged_card.size.y*0.5 77 | for holder:PlaceHolderPanel in _get_place_holders(): 78 | var rect = holder.get_global_rect() 79 | if abs(mp.y - rect.position.y) <= height or abs(mp.y - rect.end.y) <= height: 80 | if not holder.active: 81 | holder.active = true 82 | holder.change_size(_draged_card.size*0.8, place_holder_duration) 83 | else: 84 | if holder.active: 85 | holder.active = false 86 | holder.change_size(place_holder_min_size, place_holder_duration) 87 | 88 | func _start_drag(value:BaseDragableCard): 89 | _draged_card = value 90 | if not _draged_card: 91 | return 92 | _drag_offset = _draged_card.global_position-get_global_mouse_position() 93 | 94 | #_draged_card.start_drag() 95 | _previous_index = _draged_card.get_index() 96 | remove_card(_draged_card) 97 | _add_place_holder() 98 | get_tree().root.add_child(_draged_card) 99 | # 100 | _shadow_panel = _shadow_panel_packed_scene.instantiate() 101 | _draged_card.add_child(_shadow_panel) 102 | _shadow_panel.show_behind_parent = true 103 | 104 | func _draging(): 105 | if not _draged_card: 106 | return 107 | _draged_card.global_position = get_global_mouse_position()+_drag_offset 108 | _auto_change_place_holder_size() 109 | 110 | func _stop_drag(): 111 | if not _draged_card: 112 | return 113 | var index = _get_active_holder_index() 114 | if index == null: 115 | index = _previous_index 116 | get_tree().root.remove_child(_draged_card) 117 | _remove_all_place_holder() 118 | add_card(_draged_card) 119 | move_child(_draged_card, index) 120 | #_draged_card.stop_drag() 121 | _draged_card = null 122 | _shadow_panel.queue_free() 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /components/draggable_card_component/draggable_card_component.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=3 uid="uid://6u8h5mdrptp2"] 2 | 3 | [ext_resource type="Script" path="res://components/draggable_card_component/draggable_card_component.gd" id="1_toqcj"] 4 | [ext_resource type="PackedScene" uid="uid://bg8fp2m6l85w0" path="res://components/draggable_card_component/card/place_holder_panel.tscn" id="2_2jsx6"] 5 | [ext_resource type="PackedScene" uid="uid://kvt4c6h81b5i" path="res://components/draggable_card_component/card/shadow_panel.tscn" id="3_sq3sp"] 6 | 7 | [node name="DraggableCardComponent" type="VBoxContainer"] 8 | anchors_preset = 15 9 | anchor_right = 1.0 10 | anchor_bottom = 1.0 11 | grow_horizontal = 2 12 | grow_vertical = 2 13 | script = ExtResource("1_toqcj") 14 | PLACE_HOLDER_PACKED_SCENE = ExtResource("2_2jsx6") 15 | _shadow_panel_packed_scene = ExtResource("3_sq3sp") 16 | -------------------------------------------------------------------------------- /components/draggable_card_component/example/custom_card.gd: -------------------------------------------------------------------------------- 1 | extends BaseDragableCard 2 | 3 | @onready var drag_handle_texture_rect = $MarginContainer2/HBoxContainer/DragHandleTextureRect 4 | @onready var label = $MarginContainer2/HBoxContainer/Label 5 | 6 | func _ready(): 7 | drag_handle_texture_rect.button_down.connect(start_drag) 8 | 9 | func set_label(value:String): 10 | label.text = value 11 | -------------------------------------------------------------------------------- /components/draggable_card_component/example/custom_card.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=7 format=3 uid="uid://b5ovtxphyim6a"] 2 | 3 | [ext_resource type="PackedScene" uid="uid://1kesytt30cu1" path="res://components/draggable_card_component/card/base_draggable_card.tscn" id="1_grn1e"] 4 | [ext_resource type="Texture2D" uid="uid://cv3lk1pbm7kla" path="res://resource/icons/Boghma.png" id="2_daufi"] 5 | [ext_resource type="Script" path="res://components/draggable_card_component/example/custom_card.gd" id="2_qaqbv"] 6 | [ext_resource type="Texture2D" uid="uid://p00vrh0ps58s" path="res://resource/icons/drag.png" id="3_0mmr5"] 7 | 8 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_w0w3p"] 9 | bg_color = Color(0.282353, 0.329412, 0.376471, 1) 10 | corner_radius_top_left = 10 11 | corner_radius_top_right = 10 12 | corner_radius_bottom_right = 10 13 | corner_radius_bottom_left = 10 14 | 15 | [sub_resource type="LabelSettings" id="LabelSettings_rnjvn"] 16 | font_color = Color(0.823529, 0.854902, 0.886275, 1) 17 | 18 | [node name="CustomDraggableCard" instance=ExtResource("1_grn1e")] 19 | anchors_preset = 10 20 | anchor_right = 1.0 21 | offset_right = 0.0 22 | grow_horizontal = 2 23 | size_flags_horizontal = 3 24 | theme_override_styles/panel = SubResource("StyleBoxFlat_w0w3p") 25 | script = ExtResource("2_qaqbv") 26 | 27 | [node name="MarginContainer2" type="MarginContainer" parent="." index="0"] 28 | layout_mode = 2 29 | theme_override_constants/margin_left = 10 30 | theme_override_constants/margin_top = 10 31 | theme_override_constants/margin_right = 10 32 | theme_override_constants/margin_bottom = 10 33 | 34 | [node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer2" index="0"] 35 | layout_mode = 2 36 | 37 | [node name="TextureRect" type="TextureRect" parent="MarginContainer2/HBoxContainer" index="0"] 38 | custom_minimum_size = Vector2(64, 64) 39 | layout_mode = 2 40 | size_flags_horizontal = 4 41 | texture = ExtResource("2_daufi") 42 | expand_mode = 1 43 | 44 | [node name="Label" type="Label" parent="MarginContainer2/HBoxContainer" index="1"] 45 | layout_mode = 2 46 | size_flags_horizontal = 3 47 | size_flags_vertical = 1 48 | text = "Boghma" 49 | label_settings = SubResource("LabelSettings_rnjvn") 50 | 51 | [node name="DragHandleTextureRect" type="TextureButton" parent="MarginContainer2/HBoxContainer" index="2"] 52 | self_modulate = Color(0.117647, 0.152941, 0.180392, 1) 53 | custom_minimum_size = Vector2(32, 32) 54 | layout_mode = 2 55 | size_flags_horizontal = 4 56 | size_flags_vertical = 4 57 | mouse_default_cursor_shape = 2 58 | texture_normal = ExtResource("3_0mmr5") 59 | ignore_texture_size = true 60 | stretch_mode = 5 61 | -------------------------------------------------------------------------------- /components/draggable_card_component/example/draggable_card_example.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | @onready var draggable_card_component = $DraggableCardComponent 4 | 5 | @export var card_scene: PackedScene 6 | # Called when the node enters the scene tree for the first time. 7 | func _ready(): 8 | for i in range(10): 9 | var card = card_scene.instantiate() 10 | draggable_card_component.add_card(card) 11 | card.set_label("Boghma %d"%i) 12 | 13 | -------------------------------------------------------------------------------- /components/draggable_card_component/example/draggable_card_example.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=3 uid="uid://pekautnq34hp"] 2 | 3 | [ext_resource type="Script" path="res://components/draggable_card_component/example/draggable_card_example.gd" id="1_yhrqp"] 4 | [ext_resource type="PackedScene" uid="uid://b5ovtxphyim6a" path="res://components/draggable_card_component/example/custom_card.tscn" id="2_ogqgv"] 5 | [ext_resource type="PackedScene" uid="uid://6u8h5mdrptp2" path="res://components/draggable_card_component/draggable_card_component.tscn" id="3_5i1bd"] 6 | [ext_resource type="Script" path="res://boghma/scripts/free_parent_when_start.gd" id="4_dgb04"] 7 | 8 | [node name="draggable_card_example" type="Control"] 9 | layout_mode = 3 10 | anchors_preset = 15 11 | anchor_right = 1.0 12 | anchor_bottom = 1.0 13 | grow_horizontal = 2 14 | grow_vertical = 2 15 | script = ExtResource("1_yhrqp") 16 | card_scene = ExtResource("2_ogqgv") 17 | 18 | [node name="DraggableCardComponent" parent="." instance=ExtResource("3_5i1bd")] 19 | layout_mode = 1 20 | anchors_preset = 10 21 | anchor_bottom = 0.0 22 | offset_bottom = 84.0 23 | grow_vertical = 1 24 | 25 | [node name="CustomDraggableCard" parent="DraggableCardComponent" instance=ExtResource("2_ogqgv")] 26 | layout_mode = 2 27 | 28 | [node name="FPWS" type="Node" parent="DraggableCardComponent/CustomDraggableCard"] 29 | script = ExtResource("4_dgb04") 30 | -------------------------------------------------------------------------------- /components/mograph_component/effector/mograph_base_effector.gd: -------------------------------------------------------------------------------- 1 | class_name MographBaseEffector extends Control 2 | 3 | @export var strength :float = 1 4 | @export var fields :Array[MographBaseField] = [] 5 | 6 | func get_node_real_global_transform(node:Control) -> Transform2D: 7 | var trans = node.get_global_transform() 8 | var pos = trans*node.pivot_offset 9 | trans.origin = pos 10 | return trans 11 | 12 | 13 | func apply_effect(node:Control): 14 | pass 15 | 16 | 17 | func get_field_result(node:Control): 18 | var field_result = 1 19 | for field:MographBaseField in fields: 20 | if not field or not field.visible: 21 | continue 22 | ## FIXME: 多个域叠加 23 | field_result = field.get_field_result(node) 24 | return field_result 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /components/mograph_component/effector/mograph_delay_effector.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | class_name MographDelayEffector extends Control 3 | 4 | @export var enable_position := true 5 | @export var enable_rotation := true 6 | @export var enable_scale := true 7 | 8 | @export var spring:float = 500 # 1000 9 | @export var damp:float = 20 # 40 10 | 11 | @export var debug :float 12 | 13 | var _displacement :float=0 14 | var _velocity :float=0 15 | var _rand :float = 0 16 | 17 | @export var mograph_grid_container:Node 18 | 19 | var _pre :Vector2 20 | 21 | func set_velocity(value:float): 22 | _velocity = value 23 | 24 | func get_displacment(): 25 | return _displacement 26 | 27 | func _delay_update(delta:float): 28 | var force = -spring * _displacement - damp*_velocity 29 | _velocity += force*delta 30 | _displacement += _velocity*delta 31 | 32 | #func _input(event): 33 | #if event.is_pressed(): 34 | #_velocity = 1000 35 | #mograph_grid_container.align_position = Vector2(randf_range(-100,100), randf_range(-100,100)) 36 | #_pre = mograph_grid_container.align_position 37 | #func _process(delta): 38 | #_delay_update(delta) 39 | ##mograph_grid_container.align_position = _pre + Vector2(0, _displacement) 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /components/mograph_component/effector/mograph_plain_effector.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | class_name MographPlainEffector extends MographBaseEffector 3 | 4 | enum TransformSpace {Nodes, Effector, ParentContainer} 5 | @export var transform_space:=TransformSpace.Nodes 6 | 7 | @export var enable_position:= false 8 | @export var effect_position:=Vector2.ZERO 9 | @export var enable_rotation:= false 10 | @export var effect_rotation:float = 0 11 | @export var enable_scale:= false 12 | @export var effect_scale:=Vector2.ZERO 13 | @export var enable_z_index:= false 14 | @export var effect_z_index:int=0 15 | 16 | 17 | func apply_effect(node:Control): 18 | var field_result = get_field_result(node) 19 | if enable_position: 20 | ## NOTE: 注意这里要叠加相对位置 21 | node.position += get_effect_position(node)*field_result 22 | if enable_rotation: 23 | node.rotation_degrees += get_effect_rotation()*field_result 24 | if enable_scale: 25 | node.scale += get_effect_scale()*field_result 26 | if enable_z_index: 27 | node.z_index += get_effect_z_index()*field_result 28 | 29 | func get_effect_z_index(): 30 | return effect_z_index*strength 31 | 32 | func get_effect_position(node:Control): 33 | match transform_space: 34 | TransformSpace.Nodes: 35 | var parent_trans_inverse = get_node_real_global_transform(node.get_parent()).affine_inverse() 36 | var trans:Transform2D = get_node_real_global_transform(node) 37 | var rel_trans = parent_trans_inverse*trans 38 | var lp = rel_trans*(effect_position*strength) 39 | lp -= rel_trans.origin 40 | return lp 41 | TransformSpace.Effector: 42 | var parent_trans_inverse = get_node_real_global_transform(node.get_parent()).affine_inverse() 43 | var trans:Transform2D = get_node_real_global_transform(self) 44 | var rel_trans = parent_trans_inverse*trans 45 | var lp = rel_trans*(effect_position*strength) 46 | lp -= rel_trans.origin 47 | return lp 48 | TransformSpace.ParentContainer: 49 | return (effect_position*strength) 50 | 51 | func get_effect_rotation(): 52 | return effect_rotation*strength 53 | 54 | func get_effect_scale(): 55 | return effect_scale*strength 56 | 57 | -------------------------------------------------------------------------------- /components/mograph_component/effector/mograph_target_effector.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | class_name MographTargetEffector extends MographBaseEffector 3 | 4 | @export var addition:= false 5 | 6 | func apply_effect(node:Control): 7 | var field_result = get_field_result(node) 8 | 9 | var trans = get_node_real_global_transform(self) 10 | var node_trans = get_node_real_global_transform(node) 11 | var parent_trans = get_node_real_global_transform(node.get_parent()).affine_inverse() 12 | var rot = parent_trans*node_trans.looking_at(trans.origin) 13 | 14 | if addition: 15 | node.rotation += rot.get_rotation()*strength*field_result 16 | else: 17 | node.rotation = rot.get_rotation()*strength*field_result 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /components/mograph_component/example/mograph_effector_example.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=7 format=3 uid="uid://bomfdgpvkx5or"] 2 | 3 | [ext_resource type="Script" path="res://components/mograph_component/effector/mograph_target_effector.gd" id="1_popy7"] 4 | [ext_resource type="Script" path="res://components/mograph_component/effector/mograph_delay_effector.gd" id="2_febja"] 5 | [ext_resource type="Script" path="res://components/mograph_component/mograph_container/mograph_linear_container.gd" id="2_nucpo"] 6 | [ext_resource type="Script" path="res://components/mograph_component/tool/container_transform_viewer.gd" id="4_jfy7h"] 7 | 8 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_qgedt"] 9 | border_width_left = 2 10 | border_width_top = 2 11 | border_width_right = 2 12 | border_width_bottom = 2 13 | border_color = Color(0.152941, 0.152941, 0.152941, 1) 14 | corner_detail = 20 15 | 16 | [sub_resource type="Theme" id="Theme_e5qtn"] 17 | PanelContainer/styles/panel = SubResource("StyleBoxFlat_qgedt") 18 | 19 | [node name="MographEffectorExample" type="Control"] 20 | layout_mode = 3 21 | anchors_preset = 15 22 | anchor_right = 1.0 23 | anchor_bottom = 1.0 24 | grow_horizontal = 2 25 | grow_vertical = 2 26 | 27 | [node name="MographTargetEffector" type="Control" parent="."] 28 | anchors_preset = 0 29 | offset_left = 665.0 30 | offset_top = 474.0 31 | offset_right = 705.0 32 | offset_bottom = 514.0 33 | script = ExtResource("1_popy7") 34 | 35 | [node name="MographDelayEffector" type="Control" parent="." node_paths=PackedStringArray("mograph_grid_container")] 36 | visible = false 37 | anchors_preset = 0 38 | offset_left = 66.0 39 | offset_top = 94.0 40 | offset_right = 106.0 41 | offset_bottom = 134.0 42 | script = ExtResource("2_febja") 43 | spring = 400.0 44 | mograph_grid_container = NodePath("../MographGridContainer") 45 | 46 | [node name="MographGridContainer" type="Container" parent="." node_paths=PackedStringArray("effectors")] 47 | layout_mode = 0 48 | offset_left = 150.0 49 | offset_top = 191.0 50 | offset_right = 190.0 51 | offset_bottom = 231.0 52 | theme = SubResource("Theme_e5qtn") 53 | script = ExtResource("2_nucpo") 54 | linear_mode = 1 55 | step_rotation = 14788.6 56 | effectors = [NodePath("../MographTargetEffector")] 57 | 58 | [node name="PanelContainer2" type="PanelContainer" parent="MographGridContainer"] 59 | custom_minimum_size = Vector2(100, 200) 60 | layout_mode = 2 61 | size_flags_horizontal = 0 62 | size_flags_vertical = 0 63 | 64 | [node name="PanelContainer3" type="PanelContainer" parent="MographGridContainer"] 65 | custom_minimum_size = Vector2(100, 200) 66 | layout_mode = 2 67 | size_flags_horizontal = 6 68 | size_flags_vertical = 6 69 | 70 | [node name="PanelContainer4" type="PanelContainer" parent="MographGridContainer"] 71 | custom_minimum_size = Vector2(100, 200) 72 | layout_mode = 2 73 | size_flags_horizontal = 2 74 | size_flags_vertical = 6 75 | 76 | [node name="PanelContainer5" type="PanelContainer" parent="MographGridContainer"] 77 | custom_minimum_size = Vector2(100, 200) 78 | layout_mode = 2 79 | size_flags_horizontal = 6 80 | size_flags_vertical = 6 81 | 82 | [node name="PanelContainer6" type="PanelContainer" parent="MographGridContainer"] 83 | custom_minimum_size = Vector2(100, 200) 84 | layout_mode = 2 85 | size_flags_horizontal = 6 86 | size_flags_vertical = 6 87 | 88 | [node name="PanelContainer7" type="PanelContainer" parent="MographGridContainer"] 89 | custom_minimum_size = Vector2(100, 200) 90 | layout_mode = 2 91 | size_flags_horizontal = 6 92 | size_flags_vertical = 6 93 | 94 | [node name="PanelContainer8" type="PanelContainer" parent="MographGridContainer"] 95 | custom_minimum_size = Vector2(100, 200) 96 | layout_mode = 2 97 | size_flags_horizontal = 6 98 | size_flags_vertical = 6 99 | 100 | [node name="DebugViewer" type="Control" parent="." node_paths=PackedStringArray("mograph_container")] 101 | layout_mode = 3 102 | anchors_preset = 0 103 | script = ExtResource("4_jfy7h") 104 | mograph_container = NodePath("../MographGridContainer") 105 | -------------------------------------------------------------------------------- /components/mograph_component/example/mograph_grid_example.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=7 format=3 uid="uid://bofawbopk1wlm"] 2 | 3 | [ext_resource type="Script" path="res://components/mograph_component/effector/mograph_plain_effector.gd" id="1_5n4mq"] 4 | [ext_resource type="Script" path="res://components/mograph_component/mograph_container/mograph_grid_container.gd" id="1_b1mc6"] 5 | [ext_resource type="Script" path="res://components/mograph_component/field/mograph_circle_field.gd" id="2_f01mx"] 6 | [ext_resource type="Script" path="res://components/mograph_component/tool/container_transform_viewer.gd" id="4_bfltn"] 7 | 8 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_qgedt"] 9 | border_width_left = 2 10 | border_width_top = 2 11 | border_width_right = 2 12 | border_width_bottom = 2 13 | border_color = Color(0.152941, 0.152941, 0.152941, 1) 14 | corner_detail = 20 15 | 16 | [sub_resource type="Theme" id="Theme_e5qtn"] 17 | PanelContainer/styles/panel = SubResource("StyleBoxFlat_qgedt") 18 | 19 | [node name="MographGridExample" type="Control"] 20 | layout_mode = 3 21 | anchors_preset = 15 22 | anchor_right = 1.0 23 | anchor_bottom = 1.0 24 | grow_horizontal = 2 25 | grow_vertical = 2 26 | 27 | [node name="PlainEffector" type="Control" parent="." node_paths=PackedStringArray("fields")] 28 | anchors_preset = 0 29 | offset_left = 257.0 30 | offset_top = 202.0 31 | offset_right = 257.0 32 | offset_bottom = 202.0 33 | script = ExtResource("1_5n4mq") 34 | enable_scale = true 35 | effect_scale = Vector2(0.5, 0.5) 36 | enable_z_index = true 37 | effect_z_index = 2 38 | fields = [NodePath("CircleField")] 39 | 40 | [node name="CircleField" type="Control" parent="PlainEffector"] 41 | layout_mode = 3 42 | anchors_preset = 0 43 | offset_left = 32.0 44 | offset_top = 194.0 45 | offset_right = 32.0 46 | offset_bottom = 194.0 47 | script = ExtResource("2_f01mx") 48 | 49 | [node name="MographGridContainer" type="Container" parent="." node_paths=PackedStringArray("effectors")] 50 | layout_mode = 0 51 | offset_left = 193.0 52 | offset_top = 197.0 53 | offset_right = 233.0 54 | offset_bottom = 237.0 55 | theme = SubResource("Theme_e5qtn") 56 | script = ExtResource("1_b1mc6") 57 | grid_mode = 1 58 | gird_size = Vector2(110, 200) 59 | effectors = [NodePath("../PlainEffector")] 60 | 61 | [node name="PanelContainer2" type="PanelContainer" parent="MographGridContainer"] 62 | custom_minimum_size = Vector2(100, 200) 63 | layout_mode = 2 64 | size_flags_horizontal = 0 65 | size_flags_vertical = 0 66 | 67 | [node name="PanelContainer3" type="PanelContainer" parent="MographGridContainer"] 68 | custom_minimum_size = Vector2(100, 200) 69 | layout_mode = 2 70 | size_flags_horizontal = 6 71 | size_flags_vertical = 6 72 | 73 | [node name="PanelContainer4" type="PanelContainer" parent="MographGridContainer"] 74 | custom_minimum_size = Vector2(100, 200) 75 | layout_mode = 2 76 | size_flags_horizontal = 2 77 | size_flags_vertical = 6 78 | 79 | [node name="PanelContainer5" type="PanelContainer" parent="MographGridContainer"] 80 | custom_minimum_size = Vector2(100, 200) 81 | layout_mode = 2 82 | size_flags_horizontal = 6 83 | size_flags_vertical = 6 84 | 85 | [node name="PanelContainer6" type="PanelContainer" parent="MographGridContainer"] 86 | z_index = 1 87 | custom_minimum_size = Vector2(100, 200) 88 | layout_mode = 2 89 | size_flags_horizontal = 6 90 | size_flags_vertical = 6 91 | 92 | [node name="PanelContainer7" type="PanelContainer" parent="MographGridContainer"] 93 | custom_minimum_size = Vector2(100, 200) 94 | layout_mode = 2 95 | size_flags_horizontal = 6 96 | size_flags_vertical = 6 97 | 98 | [node name="PanelContainer8" type="PanelContainer" parent="MographGridContainer"] 99 | custom_minimum_size = Vector2(100, 200) 100 | layout_mode = 2 101 | size_flags_horizontal = 6 102 | size_flags_vertical = 6 103 | 104 | [node name="PanelContainer9" type="PanelContainer" parent="MographGridContainer"] 105 | custom_minimum_size = Vector2(100, 200) 106 | layout_mode = 2 107 | size_flags_horizontal = 6 108 | size_flags_vertical = 6 109 | 110 | [node name="PanelContainer10" type="PanelContainer" parent="MographGridContainer"] 111 | custom_minimum_size = Vector2(100, 200) 112 | layout_mode = 2 113 | size_flags_horizontal = 6 114 | size_flags_vertical = 6 115 | 116 | [node name="DebugViewer" type="Control" parent="." node_paths=PackedStringArray("mograph_container")] 117 | layout_mode = 3 118 | anchors_preset = 0 119 | script = ExtResource("4_bfltn") 120 | mograph_container = NodePath("../MographGridContainer") 121 | -------------------------------------------------------------------------------- /components/mograph_component/example/mograph_linear_example.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=7 format=3 uid="uid://dys63uiy6v2rw"] 2 | 3 | [ext_resource type="Script" path="res://components/mograph_component/tool/container_transform_viewer.gd" id="1_3ae4b"] 4 | [ext_resource type="Script" path="res://components/mograph_component/effector/mograph_plain_effector.gd" id="1_2252f"] 5 | [ext_resource type="Script" path="res://components/mograph_component/field/mograph_circle_field.gd" id="2_214is"] 6 | [ext_resource type="Script" path="res://components/mograph_component/mograph_container/mograph_linear_container.gd" id="3_d4gb0"] 7 | 8 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_qgedt"] 9 | border_width_left = 2 10 | border_width_top = 2 11 | border_width_right = 2 12 | border_width_bottom = 2 13 | border_color = Color(0.152941, 0.152941, 0.152941, 1) 14 | corner_detail = 20 15 | 16 | [sub_resource type="Theme" id="Theme_bpmw8"] 17 | PanelContainer/styles/panel = SubResource("StyleBoxFlat_qgedt") 18 | 19 | [node name="MographLinearExample" type="Control"] 20 | layout_mode = 3 21 | anchors_preset = 15 22 | anchor_right = 1.0 23 | anchor_bottom = 1.0 24 | offset_left = 217.0 25 | offset_top = 242.0 26 | offset_right = -142.0 27 | offset_bottom = -271.0 28 | grow_horizontal = 2 29 | grow_vertical = 2 30 | 31 | [node name="PlainEffector2" type="Control" parent="." node_paths=PackedStringArray("fields")] 32 | anchors_preset = 0 33 | offset_left = -38.0 34 | offset_top = -242.0 35 | offset_right = -38.0 36 | offset_bottom = -242.0 37 | rotation = 1.3282 38 | script = ExtResource("1_2252f") 39 | enable_scale = true 40 | effect_scale = Vector2(0.5, 0.5) 41 | enable_z_index = true 42 | effect_z_index = 3 43 | fields = [NodePath("../MographCircleField")] 44 | 45 | [node name="MographCircleField" type="Control" parent="."] 46 | anchors_preset = 0 47 | offset_left = 332.0 48 | offset_top = 27.0 49 | offset_right = 372.0 50 | offset_bottom = 67.0 51 | script = ExtResource("2_214is") 52 | radius = 200.0 53 | 54 | [node name="MographLinearContainer" type="Container" parent="." node_paths=PackedStringArray("effectors")] 55 | layout_mode = 1 56 | anchors_preset = 8 57 | anchor_left = 0.5 58 | anchor_top = 0.5 59 | anchor_right = 0.5 60 | anchor_bottom = 0.5 61 | offset_left = -212.5 62 | offset_top = -76.5 63 | offset_right = -212.5 64 | offset_bottom = -76.5 65 | grow_horizontal = 2 66 | grow_vertical = 2 67 | size_flags_horizontal = 4 68 | size_flags_vertical = 4 69 | theme = SubResource("Theme_bpmw8") 70 | script = ExtResource("3_d4gb0") 71 | linear_mode = 1 72 | align_position = Vector2(110, 0) 73 | effectors = [NodePath("../PlainEffector2")] 74 | 75 | [node name="PanelContainer2" type="PanelContainer" parent="MographLinearContainer"] 76 | custom_minimum_size = Vector2(200, 400) 77 | layout_mode = 2 78 | size_flags_horizontal = 0 79 | size_flags_vertical = 0 80 | 81 | [node name="PanelContainer3" type="PanelContainer" parent="MographLinearContainer"] 82 | custom_minimum_size = Vector2(200, 400) 83 | layout_mode = 2 84 | size_flags_horizontal = 6 85 | size_flags_vertical = 6 86 | 87 | [node name="PanelContainer4" type="PanelContainer" parent="MographLinearContainer"] 88 | z_index = 1 89 | custom_minimum_size = Vector2(200, 400) 90 | layout_mode = 2 91 | size_flags_horizontal = 2 92 | size_flags_vertical = 6 93 | 94 | [node name="PanelContainer5" type="PanelContainer" parent="MographLinearContainer"] 95 | z_index = 2 96 | custom_minimum_size = Vector2(200, 400) 97 | layout_mode = 2 98 | size_flags_horizontal = 6 99 | size_flags_vertical = 6 100 | 101 | [node name="PanelContainer6" type="PanelContainer" parent="MographLinearContainer"] 102 | z_index = 1 103 | custom_minimum_size = Vector2(200, 400) 104 | layout_mode = 2 105 | size_flags_horizontal = 6 106 | size_flags_vertical = 6 107 | 108 | [node name="PanelContainer7" type="PanelContainer" parent="MographLinearContainer"] 109 | custom_minimum_size = Vector2(200, 400) 110 | layout_mode = 2 111 | size_flags_horizontal = 6 112 | size_flags_vertical = 6 113 | 114 | [node name="PanelContainer8" type="PanelContainer" parent="MographLinearContainer"] 115 | custom_minimum_size = Vector2(200, 400) 116 | layout_mode = 2 117 | size_flags_horizontal = 6 118 | size_flags_vertical = 6 119 | 120 | [node name="DebugViewer" type="Control" parent="." node_paths=PackedStringArray("mograph_container")] 121 | anchors_preset = 0 122 | offset_left = -216.0 123 | offset_top = -239.0 124 | offset_right = -176.0 125 | offset_bottom = -199.0 126 | script = ExtResource("1_3ae4b") 127 | mograph_container = NodePath("../MographLinearContainer") 128 | -------------------------------------------------------------------------------- /components/mograph_component/example/mograph_radial_example.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=7 format=3 uid="uid://5jcxyqlhawia"] 2 | 3 | [ext_resource type="Script" path="res://components/mograph_component/mograph_container/mograph_radial_container.gd" id="1_k26rj"] 4 | [ext_resource type="Script" path="res://components/mograph_component/effector/mograph_plain_effector.gd" id="1_mlyrk"] 5 | [ext_resource type="Script" path="res://components/mograph_component/field/mograph_circle_field.gd" id="2_avdp3"] 6 | [ext_resource type="Script" path="res://components/mograph_component/tool/container_transform_viewer.gd" id="4_b727l"] 7 | 8 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_qgedt"] 9 | border_width_left = 2 10 | border_width_top = 2 11 | border_width_right = 2 12 | border_width_bottom = 2 13 | border_color = Color(0.152941, 0.152941, 0.152941, 1) 14 | corner_detail = 20 15 | 16 | [sub_resource type="Theme" id="Theme_e5qtn"] 17 | PanelContainer/styles/panel = SubResource("StyleBoxFlat_qgedt") 18 | 19 | [node name="MographRadialExample" type="Control"] 20 | layout_mode = 3 21 | anchors_preset = 15 22 | anchor_right = 1.0 23 | anchor_bottom = 1.0 24 | grow_horizontal = 2 25 | grow_vertical = 2 26 | 27 | [node name="PlainEffector" type="Control" parent="." node_paths=PackedStringArray("fields")] 28 | layout_mode = 2 29 | anchors_preset = 0 30 | offset_left = 812.0 31 | offset_top = 4.00001 32 | offset_right = 812.0 33 | offset_bottom = 4.00001 34 | rotation = 5.38559 35 | script = ExtResource("1_mlyrk") 36 | enable_position = true 37 | effect_position = Vector2(200, 0) 38 | enable_scale = true 39 | effect_scale = Vector2(0.5, 0.5) 40 | effect_z_index = 4 41 | fields = [NodePath("CircleField")] 42 | 43 | [node name="CircleField" type="Control" parent="PlainEffector"] 44 | anchors_preset = 0 45 | offset_left = -414.184 46 | offset_top = -195.388 47 | offset_right = -374.184 48 | offset_bottom = -155.388 49 | script = ExtResource("2_avdp3") 50 | 51 | [node name="MographRadialContainer" type="Container" parent="." node_paths=PackedStringArray("effectors")] 52 | layout_mode = 0 53 | offset_left = 193.0 54 | offset_top = 197.0 55 | offset_right = 233.0 56 | offset_bottom = 237.0 57 | theme = SubResource("Theme_e5qtn") 58 | script = ExtResource("1_k26rj") 59 | amount = 1.585 60 | align = true 61 | effectors = [NodePath("../PlainEffector")] 62 | 63 | [node name="PanelContainer2" type="PanelContainer" parent="MographRadialContainer"] 64 | custom_minimum_size = Vector2(100, 200) 65 | layout_mode = 2 66 | size_flags_horizontal = 0 67 | size_flags_vertical = 0 68 | 69 | [node name="PanelContainer3" type="PanelContainer" parent="MographRadialContainer"] 70 | custom_minimum_size = Vector2(100, 200) 71 | layout_mode = 2 72 | size_flags_horizontal = 6 73 | size_flags_vertical = 6 74 | 75 | [node name="PanelContainer4" type="PanelContainer" parent="MographRadialContainer"] 76 | custom_minimum_size = Vector2(100, 200) 77 | layout_mode = 2 78 | size_flags_horizontal = 2 79 | size_flags_vertical = 6 80 | 81 | [node name="PanelContainer5" type="PanelContainer" parent="MographRadialContainer"] 82 | custom_minimum_size = Vector2(100, 200) 83 | layout_mode = 2 84 | size_flags_horizontal = 6 85 | size_flags_vertical = 6 86 | 87 | [node name="PanelContainer6" type="PanelContainer" parent="MographRadialContainer"] 88 | custom_minimum_size = Vector2(100, 200) 89 | layout_mode = 2 90 | size_flags_horizontal = 6 91 | size_flags_vertical = 6 92 | 93 | [node name="PanelContainer7" type="PanelContainer" parent="MographRadialContainer"] 94 | custom_minimum_size = Vector2(100, 200) 95 | layout_mode = 2 96 | size_flags_horizontal = 6 97 | size_flags_vertical = 6 98 | 99 | [node name="DebugViewer" type="Control" parent="." node_paths=PackedStringArray("mograph_container")] 100 | layout_mode = 3 101 | anchors_preset = 0 102 | script = ExtResource("4_b727l") 103 | mograph_container = NodePath("../MographRadialContainer") 104 | -------------------------------------------------------------------------------- /components/mograph_component/field/mograph_base_field.gd: -------------------------------------------------------------------------------- 1 | class_name MographBaseField extends Control 2 | 3 | 4 | func get_node_real_global_position(node:Control): 5 | return node.get_global_transform()*node.pivot_offset 6 | 7 | func get_field_result(node:Control) -> float: 8 | return 1 9 | -------------------------------------------------------------------------------- /components/mograph_component/field/mograph_circle_field.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | class_name MographCircleField extends MographBaseField 3 | 4 | 5 | @export var radius :float = 100: 6 | set(value): 7 | radius = value 8 | queue_redraw() 9 | 10 | var _color = Color.AQUA 11 | var _width :float= 2 12 | 13 | 14 | func get_field_result(node:Control) -> float: 15 | var v1 = get_node_real_global_position(node)- global_position 16 | var field_result = remap(v1.length(), radius, 0, 0, 1.0) 17 | field_result = clamp(field_result, 0, 1) 18 | return field_result 19 | 20 | 21 | func _draw(): 22 | if not Engine.is_editor_hint(): 23 | return 24 | draw_arc(Vector2.ZERO, radius, 0, PI*2, 32, _color, _width) 25 | -------------------------------------------------------------------------------- /components/mograph_component/field/mograph_linear_field.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | class_name MographLinearField extends MographBaseField 3 | 4 | @export var length :float = 100: 5 | set(value): 6 | length = value 7 | queue_redraw() 8 | 9 | var _height = 50 10 | var _color = Color.AQUA 11 | var _width :float= 2 12 | 13 | func get_field_result(node:Control) -> float: 14 | var node_trans = node.get_global_transform() 15 | var vx = get_global_transform().x 16 | var v1 = get_node_real_global_position(node)- global_position 17 | var shadow_length = vx.dot(v1) 18 | var field_result = remap(shadow_length, -length, length, 0, 1.0) 19 | field_result = clamp(field_result, 0, 1) 20 | return field_result 21 | 22 | func _draw(): 23 | var end = -length 24 | var start = length 25 | draw_line(Vector2(end, _height*0.5), Vector2(end, -_height*0.5), _color, _width) 26 | draw_line(Vector2(start, _height), Vector2(start, -_height), _color, _width) 27 | draw_line(Vector2(end, 0), Vector2(start, -0), _color, _width) 28 | -------------------------------------------------------------------------------- /components/mograph_component/mograph_container/mograph_base_container.gd: -------------------------------------------------------------------------------- 1 | class_name MographBaseContainer extends Container 2 | 3 | @export var effectors:Array[MographBaseEffector] = [] 4 | 5 | 6 | func update(delta:float): 7 | for child:Control in get_children(): 8 | if not child is Control: 9 | continue 10 | apply_effector(child) 11 | 12 | func apply_effector(node:Control): 13 | for effector:MographBaseEffector in effectors: 14 | if not effector or not effector.visible: 15 | continue 16 | effector.apply_effect(node) 17 | 18 | -------------------------------------------------------------------------------- /components/mograph_component/mograph_container/mograph_grid_container.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | class_name MographGridContainer extends MographBaseContainer 3 | 4 | enum GridMode {EndPoint, PerStep} 5 | @export var grid_mode:= GridMode.EndPoint 6 | 7 | @export var amount :float = 1 8 | @export var grid_column:int= 3 9 | @export var gird_size := Vector2(200,200) 10 | 11 | @export var overall_center_offset := Vector2(0.5,0.5) 12 | @export var aling_z :int=0 13 | 14 | func _process(delta): 15 | update(delta) 16 | 17 | func update(delta): 18 | var grid_column = max(grid_column, 1) 19 | var count = get_child_count() 20 | if count<=1: 21 | return 22 | 23 | var position_each = gird_size*amount 24 | var z_each = aling_z 25 | if grid_mode == GridMode.EndPoint: 26 | position_each /= count-1 27 | 28 | for child:Control in get_children(): 29 | if not child is Control: 30 | continue 31 | var index = child.get_index() 32 | var column = index%grid_column 33 | var row = index/grid_column 34 | child.pivot_offset = child.size*overall_center_offset 35 | child.position = position_each*Vector2(column, row) - child.pivot_offset 36 | child.z_index = z_each*index 37 | child.size = child.custom_minimum_size 38 | child.rotation_degrees = 0 39 | child.scale = Vector2.ONE 40 | 41 | super(delta) 42 | -------------------------------------------------------------------------------- /components/mograph_component/mograph_container/mograph_linear_container.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | class_name MographLinearContainer extends MographBaseContainer 3 | 4 | enum LinearMode {EndPoint, PerStep} 5 | @export var linear_mode:= LinearMode.EndPoint 6 | @export var amount :float = 1 7 | 8 | @export var align_position:= Vector2(100,0) 9 | @export var align_rotation:float = 0 10 | @export var align_scale := Vector2(1,1) 11 | @export var overall_center_offset := Vector2(0.5,0.5) 12 | @export var aling_z :int=0 13 | 14 | @export var step_rotation:float = 0 15 | 16 | 17 | func _process(delta): 18 | update(delta) 19 | 20 | func update(delta): 21 | var count = get_child_count() 22 | if count<=1: 23 | return 24 | var rotate_each = align_rotation*amount 25 | var scale_each = func(index): return Vector2(pow(align_scale.x, index), pow(align_scale.y, index)) 26 | var position_each = align_position*amount 27 | var z_each = aling_z 28 | if linear_mode == LinearMode.EndPoint: 29 | position_each /= count-1 30 | rotate_each /= count-1 31 | scale_each = func(index): 32 | var _exp = index/float(count) 33 | return Vector2(pow(align_scale.x, _exp), pow(align_scale.y, _exp)) 34 | 35 | 36 | var rotation_trans_call = func(index): return Transform2D(deg_to_rad(step_rotation*index), Vector2.ZERO) 37 | var pre_pos :=Vector2.ZERO 38 | 39 | for child:Control in get_children(): 40 | if not child is Control: 41 | continue 42 | var index = child.get_index() 43 | child.pivot_offset = child.size*overall_center_offset 44 | child.position = pre_pos - child.pivot_offset 45 | pre_pos += rotation_trans_call.call(index)*position_each 46 | child.z_index = z_each*index 47 | child.size = child.custom_minimum_size 48 | child.rotation_degrees = rotate_each*index + step_rotation*index 49 | child.scale = scale_each.call(index) 50 | 51 | apply_effector(child) 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /components/mograph_component/mograph_container/mograph_radial_container.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | class_name MographRadialContainer extends MographBaseContainer 3 | 4 | @export var amount :float = 1 5 | @export var radius :float = 100 6 | 7 | @export var start_angle:float = 0 8 | @export var end_angle:float = 360 9 | @export var offset_angle:float = 0 10 | 11 | @export var align:= false 12 | 13 | @export var overall_center_offset := Vector2(0.5,0.5) 14 | @export var aling_z :int=0 15 | 16 | func _process(delta): 17 | update(delta) 18 | 19 | func update(delta): 20 | var count = get_child_count() 21 | if count<=1: 22 | return 23 | 24 | var z_each = aling_z 25 | var d_each = (end_angle-start_angle)/count 26 | var final_pos = func(index): return Transform2D(deg_to_rad(start_angle + d_each*index +offset_angle), Vector2.ZERO)*Vector2(radius*amount, 0) 27 | 28 | for child:Control in get_children(): 29 | if not child is Control: 30 | continue 31 | var index = child.get_index() 32 | child.pivot_offset = child.size*overall_center_offset 33 | child.position = final_pos.call(index) - child.pivot_offset 34 | child.z_index = z_each*index 35 | child.size = child.custom_minimum_size 36 | if align: 37 | child.rotation_degrees = start_angle + d_each*index +offset_angle 38 | else: 39 | child.rotation_degrees = 0 40 | child.scale = Vector2.ONE 41 | 42 | super(delta) 43 | -------------------------------------------------------------------------------- /components/mograph_component/test/control_1.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene format=3 uid="uid://4lfo5wnagh1c"] 2 | 3 | [node name="Control1" type="Control"] 4 | layout_mode = 3 5 | anchors_preset = 15 6 | anchor_right = 1.0 7 | anchor_bottom = 1.0 8 | grow_horizontal = 2 9 | grow_vertical = 2 10 | pivot_offset = Vector2(100, 100) 11 | 12 | [node name="Control2" type="Control" parent="."] 13 | anchors_preset = 0 14 | offset_left = 191.0 15 | offset_top = 119.0 16 | offset_right = 231.0 17 | offset_bottom = 159.0 18 | rotation = 0.685914 19 | scale = Vector2(2, 2) 20 | pivot_offset = Vector2(50, 50) 21 | 22 | [node name="Control3" type="Control" parent="Control2"] 23 | anchors_preset = 0 24 | offset_left = 98.384 25 | offset_top = 67.688 26 | offset_right = 138.384 27 | offset_bottom = 107.688 28 | rotation = 0.785398 29 | pivot_offset = Vector2(50, 50) 30 | 31 | [node name="Control4" type="Control" parent="Control2/Control3"] 32 | anchors_preset = 0 33 | offset_left = 50.9579 34 | offset_top = -79.0198 35 | offset_right = 90.9579 36 | offset_bottom = -39.0198 37 | rotation = -0.314159 38 | pivot_offset = Vector2(54.29, 50) 39 | -------------------------------------------------------------------------------- /components/mograph_component/tool/container_transform_viewer.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends Control 3 | 4 | @export var mograph_container:MographBaseContainer 5 | 6 | 7 | func get_node_real_global_transform(node:Control) -> Transform2D: 8 | var trans = node.get_global_transform() 9 | var pos = trans*node.pivot_offset 10 | trans.origin = pos 11 | return trans 12 | 13 | func _process(delta): 14 | queue_redraw() 15 | 16 | func draw_arrow(pos, dir:Vector2, length:float=200, width:float=1, color:= Color.AZURE): 17 | var to = pos+dir*length 18 | draw_line(pos, to, color, width, true) 19 | draw_line(to, to-dir.rotated(deg_to_rad(45))*length*0.1,color, width, true) 20 | draw_line(to, to-dir.rotated(deg_to_rad(-45))*length*0.1, color, width, true) 21 | 22 | func draw_trans(trans:Transform2D, length:float=200, width:float= 1): 23 | draw_arrow(trans.origin, trans.x, length, width, Color.RED) 24 | draw_arrow(trans.origin, trans.y, length, width, Color.GREEN_YELLOW) 25 | 26 | func _draw(): 27 | if not mograph_container: 28 | return 29 | var g_trans = get_node_real_global_transform(self) 30 | var trans = get_node_real_global_transform(mograph_container) 31 | draw_trans(g_trans.affine_inverse()*trans,100) 32 | for child in mograph_container.get_children(): 33 | trans = get_node_real_global_transform(child) 34 | draw_trans(g_trans.affine_inverse()*trans,50) 35 | 36 | -------------------------------------------------------------------------------- /example/custom_iterator/custom_iterator.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | func _ready(): 4 | iterate_tree() 5 | 6 | func iterate_tree(): 7 | var tree = Tree.new() 8 | add_child(tree) 9 | var root = tree.create_item() 10 | root.set_text(0, "root") 11 | tree.hide_root = true 12 | for i in range(10): 13 | var child = tree.create_item(root) 14 | child.set_text(0, "child"+str(i)) 15 | for j in range(10): 16 | var subchild = tree.create_item(child) 17 | subchild.set_text(0, "Subchild"+str(j)) 18 | 19 | for f in CustomIterator.TreeStructureIterator.new(root): 20 | var n = f.get_text(0) 21 | if n.begins_with("S"): 22 | print("\t", n) 23 | else: 24 | print(n) 25 | 26 | func iterate_directory(): 27 | var path = r"G:\obsidian" 28 | for f in CustomIterator.DirectoryIterator.new(path): 29 | print(f) 30 | 31 | func enumerate_array(): 32 | var iterator = CustomIterator.Enumerate.new([123,2,3,4]) 33 | for data in iterator: 34 | print(data.index, "-",data.value) 35 | 36 | for data in iterator: 37 | print(data.index, "-",data.value) 38 | 39 | -------------------------------------------------------------------------------- /example/custom_iterator/custom_iterator.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://cv8jr3kf5geyo"] 2 | 3 | [ext_resource type="Script" path="res://example/custom_iterator/custom_iterator.gd" id="1_elgff"] 4 | 5 | [node name="CustomIterator" type="Control"] 6 | layout_mode = 3 7 | anchors_preset = 15 8 | anchor_right = 1.0 9 | anchor_bottom = 1.0 10 | grow_horizontal = 2 11 | grow_vertical = 2 12 | script = ExtResource("1_elgff") 13 | -------------------------------------------------------------------------------- /example/factory/example_factory.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | enum ElementType { 4 | Element, 5 | ElementRect, 6 | ElementCircle, 7 | ElementEllipse, 8 | } 9 | 10 | var factory := Factory.new() 11 | 12 | class Element extends UniformData: 13 | @export var title:String = "" 14 | func get_title(): 15 | return title 16 | func set_title(value:String): 17 | title = value 18 | 19 | class ElementRect extends Element: 20 | @export var rect:Rect2 21 | func get_rect(): 22 | return rect 23 | func set_rect(value:Rect2): 24 | rect = value 25 | 26 | class ElementCircle extends Element: 27 | @export var center:Vector2 28 | @export var radius:float 29 | @export var is_ellipse:bool = false 30 | 31 | func get_center(): 32 | return center 33 | func set_center(value:Vector2): 34 | center = value 35 | 36 | 37 | func _ready(): 38 | var solution = 3 39 | match solution: 40 | 0: 41 | print("方法0") 42 | create_0() 43 | 1: 44 | print("方法1") 45 | create_1() 46 | 2: 47 | print("方法2") 48 | register_2() 49 | create_2() 50 | 3: 51 | print("方法3") 52 | register_3() 53 | create_3() 54 | 55 | 56 | #region 0:"直接创建 57 | ## 非常混沌,有种原始的美感 58 | func create_0(): 59 | var element = Element.new() 60 | element._type = ElementType.Element 61 | element._type_string = "Element" 62 | element.set_title("element") 63 | 64 | var rect = ElementRect.new() 65 | rect._type = ElementType.ElementRect 66 | rect._type_string = "ElementRect" 67 | rect.set_title("rect") 68 | element.add_child(rect) 69 | 70 | var rect_child = ElementRect.new() 71 | rect._type = ElementType.ElementRect 72 | rect._type_string = "ElementRect" 73 | rect_child.set_title("rect_child") 74 | rect.add_child(rect_child) 75 | 76 | var circle = ElementCircle.new() 77 | circle._type = ElementType.ElementCircle 78 | circle._type_string = "ElementCircle" 79 | circle.set_title("circle") 80 | element.add_child(circle) 81 | 82 | var circle2 = ElementCircle.new() 83 | circle2._type = ElementType.ElementEllipse 84 | circle2._type_string = "ElementEllipse" 85 | circle2.set_title("circle_ellipse") 86 | circle2.is_ellipse = true 87 | circle.add_child(circle2) 88 | 89 | print_element_tree(element) 90 | 91 | #endregion 92 | 93 | #region 1:"通过创建方法来创建" 94 | ## 已经出现工厂模式的雏形,但注册行为只能发生在当前函数内 95 | ## 也就是说任何时候需要新增类型都要修改当前的函数 96 | func create_element(type:ElementType, title:String): 97 | var element:Element 98 | match type: 99 | ElementType.Element: 100 | element = Element.new() 101 | element._type_string = "Element" 102 | ElementType.ElementRect: 103 | element = ElementRect.new() 104 | element._type_string = "ElementRect" 105 | ElementType.ElementCircle: 106 | element = ElementCircle.new() 107 | element._type_string = "ElementCircle" 108 | ElementType.ElementEllipse: 109 | element = ElementCircle.new() 110 | element._type_string = "ElementEllipse" 111 | element.is_ellipse = true 112 | _: 113 | push_error("type not valid") 114 | element._type = type 115 | element.set_title(title) 116 | return element 117 | 118 | func create_1(): 119 | var element = create_element(ElementType.Element, "element") 120 | 121 | var rect = create_element(ElementType.ElementRect, "rect") 122 | element.add_child(rect) 123 | 124 | var rect_child = create_element(ElementType.ElementRect, "rect_child") 125 | rect.add_child(rect_child) 126 | 127 | var circle = create_element(ElementType.ElementCircle, "circle") 128 | element.add_child(circle) 129 | 130 | var circle2 = create_element(ElementType.ElementEllipse, "circle_ellipse") 131 | circle.add_child(circle2) 132 | 133 | print_element_tree(element) 134 | 135 | #endregion 136 | 137 | #region 2:"最基础工厂方法创建" 138 | ## 灵活的注册对象,注册行为可以发生在任何一个能获取到factory对象的位置 139 | func register_2(): 140 | factory.register(ElementType.Element, func(): 141 | var element = Element.new() 142 | element._type = ElementType.Element 143 | element._type_string = "Element" 144 | return element 145 | ) 146 | factory.register(ElementType.ElementRect, func(): 147 | var element = ElementRect.new() 148 | element._type = ElementType.ElementRect 149 | element._type_string = "ElementRect" 150 | return element 151 | ) 152 | factory.register(ElementType.ElementCircle, func(): 153 | var element = ElementCircle.new() 154 | element._type = ElementType.ElementCircle 155 | element._type_string = "ElementCircle" 156 | return element 157 | ) 158 | factory.register(ElementType.ElementEllipse, func(): 159 | var element = ElementCircle.new() 160 | element._type = ElementType.ElementEllipse 161 | element._type_string = "ElementEllipse" 162 | element.is_ellipse = true 163 | return element 164 | ) 165 | 166 | func create_2(): 167 | var element = factory.create(ElementType.Element) 168 | element.set_title("element") 169 | 170 | var rect = factory.create(ElementType.ElementRect) 171 | rect.set_title("rect") 172 | element.add_child(rect) 173 | 174 | var rect_child = factory.create(ElementType.ElementRect) 175 | rect_child.set_title("rect_child") 176 | rect.add_child(rect_child) 177 | 178 | var circle = factory.create(ElementType.ElementCircle) 179 | circle.set_title("circle") 180 | element.add_child(circle) 181 | 182 | var circle2 = factory.create(ElementType.ElementEllipse) 183 | circle2.set_title("circle_ellipse") 184 | circle.add_child(circle2) 185 | 186 | print_element_tree(element) 187 | 188 | #endregion 189 | 190 | #region 3:"进阶的工厂方法创建" 191 | ## 工厂模式的完美形态,发挥面向对象的真正实力 192 | func simple_register(type:ElementType, object:Object, type_string:String, init_call:Callable=Callable()): 193 | factory.register(type, func(): 194 | var element = object.new() 195 | element._type = type 196 | element._type_string = type_string 197 | if init_call: 198 | init_call.call(element) 199 | return element 200 | ) 201 | 202 | func register_3(): 203 | factory.custom_register = simple_register 204 | simple_register(ElementType.Element, Element, "Element") 205 | factory.custom_register.call(ElementType.ElementRect, ElementRect, "ElementRect") 206 | simple_register(ElementType.ElementCircle, ElementCircle, "ElementCircle") 207 | simple_register(ElementType.ElementEllipse, ElementCircle, "ElementEllipse", func(e): e.is_ellipse = true) 208 | 209 | func simple_create(type:ElementType, title:String): 210 | var element = factory.create(type) 211 | element.set_title(title) 212 | return element 213 | 214 | func create_3(): 215 | factory.custom_create = simple_create 216 | var element = simple_create(ElementType.Element, "element") 217 | 218 | var rect = simple_create(ElementType.ElementRect, "rect") 219 | element.add_child(rect) 220 | 221 | var rect_child = factory.custom_create.call(ElementType.ElementRect, "rect_child") 222 | rect.add_child(rect_child) 223 | 224 | var circle = simple_create(ElementType.ElementCircle, "circle") 225 | element.add_child(circle) 226 | 227 | var circle2 = simple_create(ElementType.ElementEllipse, "circle_ellipse") 228 | circle.add_child(circle2) 229 | 230 | print_element_tree(element) 231 | #endregion 232 | 233 | ## Utils 234 | func print_element_tree(element:Element, level:int=0): 235 | print("\t".repeat(level), element.get_title(), element) 236 | for child in element.get_children(): 237 | print_element_tree(child, level+1) 238 | -------------------------------------------------------------------------------- /example/factory/example_factory.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://b830ut4mhtuf7"] 2 | 3 | [ext_resource type="Script" path="res://example/factory/example_factory.gd" id="1_quuum"] 4 | 5 | [node name="example_factory" type="Control"] 6 | layout_mode = 3 7 | anchors_preset = 15 8 | anchor_right = 1.0 9 | anchor_bottom = 1.0 10 | grow_horizontal = 2 11 | grow_vertical = 2 12 | script = ExtResource("1_quuum") 13 | -------------------------------------------------------------------------------- /example/result_helper/example_result_helper.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | var http_requests := [] 4 | 5 | func _ready(): 6 | var result_helper := download("user://test.zip", "https://xxxx.zip") 7 | 8 | result_helper.successed.connect(func(): 9 | print(result_helper.get_meta("data")) 10 | ) 11 | result_helper.failed.connect(func(): 12 | print(result_helper.get_meta("data")) 13 | ) 14 | result_helper.updated.connect(func(db): 15 | print(db) 16 | ) 17 | if result_helper.is_error_occurred(): 18 | print("download error") 19 | return 20 | 21 | func _process(delta): 22 | for http_request in http_requests: 23 | if not http_request.has_meta("result_helper"): 24 | continue 25 | var result_helper = http_request.get_meta("result_helper") 26 | var downloaded_bytes = http_request.get_downloaded_bytes() 27 | result_helper.update(downloaded_bytes) 28 | 29 | func download(path, url_link) -> ResultHelper: 30 | var result_helper := ResultHelper.new() 31 | var http_request = HTTPRequest.new() 32 | http_requests.append(http_request) 33 | add_child(http_request) 34 | http_request.set_meta("result_helper", result_helper) 35 | http_request.request_completed.connect(func(result, response_code, headers, body): 36 | http_requests.erase(http_request) 37 | http_request.queue_free() 38 | if result == OK: 39 | result_helper.set_meta("data", {"path":path}) 40 | result_helper.success() 41 | else: 42 | push_error("Download Failed") 43 | result_helper.set_meta("data", {"result":result,"response_code":response_code}) 44 | result_helper.fail() 45 | ) 46 | http_request.set_download_file(path) 47 | var request = http_request.request(url_link) 48 | if request != OK: 49 | push_error("Http request error") 50 | result_helper.error() 51 | http_requests.erase(http_request) 52 | http_request.queue_free() 53 | return result_helper 54 | -------------------------------------------------------------------------------- /example/result_helper/example_result_helper.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://mx1ax6h6ny6c"] 2 | 3 | [ext_resource type="Script" path="res://example/result_helper/example_result_helper.gd" id="1_ipian"] 4 | 5 | [sub_resource type="GDScript" id="GDScript_egsax"] 6 | script/source = "extends Node 7 | 8 | 9 | func _ready(): 10 | var x = Object.new() 11 | var f = func(): 12 | print(x) 13 | print(is_instance_valid(x)) 14 | pass 15 | x.free() 16 | f.call() 17 | " 18 | 19 | [node name="ExampleResultHelper" type="Node"] 20 | script = ExtResource("1_ipian") 21 | 22 | [node name="Node" type="Node" parent="."] 23 | script = SubResource("GDScript_egsax") 24 | -------------------------------------------------------------------------------- /globals/debug/debug_panel.gd: -------------------------------------------------------------------------------- 1 | extends CanvasLayer 2 | 3 | signal debug_draw(ua:CanvasItem) 4 | 5 | @onready var rich_text_label = %RichTextLabel 6 | @onready var canvas = %Draw 7 | 8 | var _info := {} 9 | 10 | func _ready(): 11 | canvas.draw.connect(func(): 12 | debug_draw.emit(canvas) 13 | ) 14 | 15 | func _process(delta): 16 | canvas.queue_redraw() 17 | 18 | func clear(): 19 | _info = {} 20 | update() 21 | 22 | func info(key, text): 23 | _info[key] = text 24 | update() 25 | 26 | func update(): 27 | var str = JSON.stringify(_info, "\t") 28 | str = str.trim_prefix("{\n") 29 | str = str.trim_suffix("\n}") 30 | rich_text_label.text = str 31 | 32 | -------------------------------------------------------------------------------- /globals/debug/debug_panel.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://bjmballsdbhse"] 2 | 3 | [ext_resource type="Script" path="res://globals/debug/debug_panel.gd" id="1_uvm66"] 4 | 5 | [node name="Debug" type="CanvasLayer"] 6 | layer = 5 7 | script = ExtResource("1_uvm66") 8 | 9 | [node name="Debug" type="Control" parent="."] 10 | layout_mode = 3 11 | anchors_preset = 15 12 | anchor_right = 1.0 13 | anchor_bottom = 1.0 14 | grow_horizontal = 2 15 | grow_vertical = 2 16 | mouse_filter = 2 17 | 18 | [node name="RichTextLabel" type="RichTextLabel" parent="Debug"] 19 | unique_name_in_owner = true 20 | layout_mode = 1 21 | anchors_preset = 1 22 | anchor_left = 1.0 23 | anchor_right = 1.0 24 | offset_left = -61.0 25 | offset_bottom = 25.0 26 | grow_horizontal = 0 27 | mouse_filter = 2 28 | text = "123" 29 | fit_content = true 30 | autowrap_mode = 0 31 | 32 | [node name="Draw" type="Control" parent="."] 33 | unique_name_in_owner = true 34 | layout_mode = 3 35 | anchors_preset = 15 36 | anchor_right = 1.0 37 | anchor_bottom = 1.0 38 | grow_horizontal = 2 39 | grow_vertical = 2 40 | mouse_filter = 2 41 | -------------------------------------------------------------------------------- /icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /icon.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://wlhcbu7iodu2" 6 | path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://icon.svg" 14 | dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.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 | -------------------------------------------------------------------------------- /project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=5 10 | 11 | [application] 12 | 13 | config/name="Application Components" 14 | config/tags=PackedStringArray("软件开发系列教程") 15 | run/main_scene="res://example/factory/example_factory.tscn" 16 | config/features=PackedStringArray("4.3", "Forward Plus") 17 | config/icon="res://icon.svg" 18 | 19 | [display] 20 | 21 | window/size/viewport_width=800 22 | window/size/viewport_height=800 23 | 24 | [dotnet] 25 | 26 | project/assembly_name="Application Components" 27 | 28 | [file_customization] 29 | 30 | folder_colors={ 31 | "res://boghma/": "yellow", 32 | "res://example/factory/": "green" 33 | } 34 | -------------------------------------------------------------------------------- /resource/clear icon cache on window.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | set iconcache=%localappdata%\IconCache.db 3 | set iconcache_x=%localappdata%\Microsoft\Windows\Explorer\iconcache* 4 | 5 | echo. 6 | echo The explorer process must be temporarily killed before deleting the IconCache.db file. 7 | echo. 8 | echo Please SAVE ALL OPEN WORK before continuing. 9 | echo. 10 | pause 11 | echo. 12 | If exist "%iconcache%" goto delete 13 | echo. 14 | echo The %localappdata%\IconCache.db file has already been deleted. 15 | echo. 16 | If exist "%iconcache_x%" goto delete 17 | echo. 18 | echo The %localappdata%\Microsoft\Windows\Explorer\IconCache_*.db files have already been deleted. 19 | echo. 20 | exit /B 21 | 22 | :delete 23 | echo. 24 | echo Attempting to delete IconCache.db files... 25 | echo. 26 | ie4uinit.exe -show 27 | taskkill /IM explorer.exe /F 28 | timeout /t 2 >nul 29 | del /A /F /Q "%iconcache%" 30 | del /A /F /Q "%iconcache_x%" 31 | start explorer.exe -------------------------------------------------------------------------------- /resource/fonts/NotosansSC/NotoSansCJK-Black-7.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JACKADUX/Application-Components/42861c0ada6148160223015db656de2325d3e3e3/resource/fonts/NotosansSC/NotoSansCJK-Black-7.otf -------------------------------------------------------------------------------- /resource/fonts/NotosansSC/NotoSansCJK-Black-7.otf.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="font_data_dynamic" 4 | type="FontFile" 5 | uid="uid://b0eolvu8j3gkd" 6 | path="res://.godot/imported/NotoSansCJK-Black-7.otf-b9fbeba5878a615f51fc66289fb189a1.fontdata" 7 | 8 | [deps] 9 | 10 | source_file="res://resource/fonts/NotosansSC/NotoSansCJK-Black-7.otf" 11 | dest_files=["res://.godot/imported/NotoSansCJK-Black-7.otf-b9fbeba5878a615f51fc66289fb189a1.fontdata"] 12 | 13 | [params] 14 | 15 | Rendering=null 16 | antialiasing=1 17 | generate_mipmaps=false 18 | disable_embedded_bitmaps=true 19 | multichannel_signed_distance_field=false 20 | msdf_pixel_range=8 21 | msdf_size=48 22 | allow_system_fallback=true 23 | force_autohinter=false 24 | hinting=1 25 | subpixel_positioning=1 26 | oversampling=0.0 27 | Fallbacks=null 28 | fallbacks=[] 29 | Compress=null 30 | compress=true 31 | preload=[] 32 | language_support={} 33 | script_support={} 34 | opentype_features={} 35 | -------------------------------------------------------------------------------- /resource/fonts/NotosansSC/NotoSansCJK-Bold-6.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JACKADUX/Application-Components/42861c0ada6148160223015db656de2325d3e3e3/resource/fonts/NotosansSC/NotoSansCJK-Bold-6.otf -------------------------------------------------------------------------------- /resource/fonts/NotosansSC/NotoSansCJK-Bold-6.otf.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="font_data_dynamic" 4 | type="FontFile" 5 | uid="uid://csp5mbqoeiltp" 6 | path="res://.godot/imported/NotoSansCJK-Bold-6.otf-7c9853c2cb5711b6a1f884b80a835f63.fontdata" 7 | 8 | [deps] 9 | 10 | source_file="res://resource/fonts/NotosansSC/NotoSansCJK-Bold-6.otf" 11 | dest_files=["res://.godot/imported/NotoSansCJK-Bold-6.otf-7c9853c2cb5711b6a1f884b80a835f63.fontdata"] 12 | 13 | [params] 14 | 15 | Rendering=null 16 | antialiasing=1 17 | generate_mipmaps=false 18 | disable_embedded_bitmaps=true 19 | multichannel_signed_distance_field=false 20 | msdf_pixel_range=8 21 | msdf_size=48 22 | allow_system_fallback=true 23 | force_autohinter=false 24 | hinting=1 25 | subpixel_positioning=1 26 | oversampling=0.0 27 | Fallbacks=null 28 | fallbacks=[] 29 | Compress=null 30 | compress=true 31 | preload=[] 32 | language_support={} 33 | script_support={} 34 | opentype_features={} 35 | -------------------------------------------------------------------------------- /resource/fonts/NotosansSC/NotoSansCJK-DemiLight-4.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JACKADUX/Application-Components/42861c0ada6148160223015db656de2325d3e3e3/resource/fonts/NotosansSC/NotoSansCJK-DemiLight-4.otf -------------------------------------------------------------------------------- /resource/fonts/NotosansSC/NotoSansCJK-DemiLight-4.otf.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="font_data_dynamic" 4 | type="FontFile" 5 | uid="uid://c7ki30rtlgu8m" 6 | path="res://.godot/imported/NotoSansCJK-DemiLight-4.otf-38b4b01a2bfe0b816fb3ed08cd05630b.fontdata" 7 | 8 | [deps] 9 | 10 | source_file="res://resource/fonts/NotosansSC/NotoSansCJK-DemiLight-4.otf" 11 | dest_files=["res://.godot/imported/NotoSansCJK-DemiLight-4.otf-38b4b01a2bfe0b816fb3ed08cd05630b.fontdata"] 12 | 13 | [params] 14 | 15 | Rendering=null 16 | antialiasing=1 17 | generate_mipmaps=false 18 | disable_embedded_bitmaps=true 19 | multichannel_signed_distance_field=false 20 | msdf_pixel_range=8 21 | msdf_size=48 22 | allow_system_fallback=true 23 | force_autohinter=false 24 | hinting=1 25 | subpixel_positioning=1 26 | oversampling=0.0 27 | Fallbacks=null 28 | fallbacks=[] 29 | Compress=null 30 | compress=true 31 | preload=[] 32 | language_support={} 33 | script_support={} 34 | opentype_features={} 35 | -------------------------------------------------------------------------------- /resource/fonts/NotosansSC/NotoSansCJK-Light-3.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JACKADUX/Application-Components/42861c0ada6148160223015db656de2325d3e3e3/resource/fonts/NotosansSC/NotoSansCJK-Light-3.otf -------------------------------------------------------------------------------- /resource/fonts/NotosansSC/NotoSansCJK-Light-3.otf.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="font_data_dynamic" 4 | type="FontFile" 5 | uid="uid://mi3c53nu5vvv" 6 | path="res://.godot/imported/NotoSansCJK-Light-3.otf-9283f31e4398f15b7cb8ec65a947fea2.fontdata" 7 | 8 | [deps] 9 | 10 | source_file="res://resource/fonts/NotosansSC/NotoSansCJK-Light-3.otf" 11 | dest_files=["res://.godot/imported/NotoSansCJK-Light-3.otf-9283f31e4398f15b7cb8ec65a947fea2.fontdata"] 12 | 13 | [params] 14 | 15 | Rendering=null 16 | antialiasing=1 17 | generate_mipmaps=false 18 | disable_embedded_bitmaps=true 19 | multichannel_signed_distance_field=false 20 | msdf_pixel_range=8 21 | msdf_size=48 22 | allow_system_fallback=true 23 | force_autohinter=false 24 | hinting=1 25 | subpixel_positioning=1 26 | oversampling=0.0 27 | Fallbacks=null 28 | fallbacks=[] 29 | Compress=null 30 | compress=true 31 | preload=[] 32 | language_support={} 33 | script_support={} 34 | opentype_features={} 35 | -------------------------------------------------------------------------------- /resource/fonts/NotosansSC/NotoSansCJK-Medium-5.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JACKADUX/Application-Components/42861c0ada6148160223015db656de2325d3e3e3/resource/fonts/NotosansSC/NotoSansCJK-Medium-5.otf -------------------------------------------------------------------------------- /resource/fonts/NotosansSC/NotoSansCJK-Medium-5.otf.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="font_data_dynamic" 4 | type="FontFile" 5 | uid="uid://nr7kn651bt7v" 6 | path="res://.godot/imported/NotoSansCJK-Medium-5.otf-8a45efec2191988424b3624c6e98ec19.fontdata" 7 | 8 | [deps] 9 | 10 | source_file="res://resource/fonts/NotosansSC/NotoSansCJK-Medium-5.otf" 11 | dest_files=["res://.godot/imported/NotoSansCJK-Medium-5.otf-8a45efec2191988424b3624c6e98ec19.fontdata"] 12 | 13 | [params] 14 | 15 | Rendering=null 16 | antialiasing=1 17 | generate_mipmaps=false 18 | disable_embedded_bitmaps=true 19 | multichannel_signed_distance_field=false 20 | msdf_pixel_range=8 21 | msdf_size=48 22 | allow_system_fallback=true 23 | force_autohinter=false 24 | hinting=1 25 | subpixel_positioning=1 26 | oversampling=0.0 27 | Fallbacks=null 28 | fallbacks=[] 29 | Compress=null 30 | compress=true 31 | preload=[] 32 | language_support={} 33 | script_support={} 34 | opentype_features={} 35 | -------------------------------------------------------------------------------- /resource/fonts/NotosansSC/NotoSansCJK-Regular-1.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JACKADUX/Application-Components/42861c0ada6148160223015db656de2325d3e3e3/resource/fonts/NotosansSC/NotoSansCJK-Regular-1.otf -------------------------------------------------------------------------------- /resource/fonts/NotosansSC/NotoSansCJK-Regular-1.otf.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="font_data_dynamic" 4 | type="FontFile" 5 | uid="uid://dx0b1xxlgdg7w" 6 | path="res://.godot/imported/NotoSansCJK-Regular-1.otf-7674df72aedfc2ebe0e5b3c56677718d.fontdata" 7 | 8 | [deps] 9 | 10 | source_file="res://resource/fonts/NotosansSC/NotoSansCJK-Regular-1.otf" 11 | dest_files=["res://.godot/imported/NotoSansCJK-Regular-1.otf-7674df72aedfc2ebe0e5b3c56677718d.fontdata"] 12 | 13 | [params] 14 | 15 | Rendering=null 16 | antialiasing=1 17 | generate_mipmaps=false 18 | disable_embedded_bitmaps=true 19 | multichannel_signed_distance_field=false 20 | msdf_pixel_range=8 21 | msdf_size=48 22 | allow_system_fallback=true 23 | force_autohinter=false 24 | hinting=1 25 | subpixel_positioning=1 26 | oversampling=0.0 27 | Fallbacks=null 28 | fallbacks=[] 29 | Compress=null 30 | compress=true 31 | preload=[] 32 | language_support={} 33 | script_support={} 34 | opentype_features={} 35 | -------------------------------------------------------------------------------- /resource/fonts/NotosansSC/NotoSansCJK-Thin-2.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JACKADUX/Application-Components/42861c0ada6148160223015db656de2325d3e3e3/resource/fonts/NotosansSC/NotoSansCJK-Thin-2.otf -------------------------------------------------------------------------------- /resource/fonts/NotosansSC/NotoSansCJK-Thin-2.otf.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="font_data_dynamic" 4 | type="FontFile" 5 | uid="uid://gwiesw1sqtcr" 6 | path="res://.godot/imported/NotoSansCJK-Thin-2.otf-870bd4e86878492563dcb1aae74507ab.fontdata" 7 | 8 | [deps] 9 | 10 | source_file="res://resource/fonts/NotosansSC/NotoSansCJK-Thin-2.otf" 11 | dest_files=["res://.godot/imported/NotoSansCJK-Thin-2.otf-870bd4e86878492563dcb1aae74507ab.fontdata"] 12 | 13 | [params] 14 | 15 | Rendering=null 16 | antialiasing=1 17 | generate_mipmaps=false 18 | disable_embedded_bitmaps=true 19 | multichannel_signed_distance_field=false 20 | msdf_pixel_range=8 21 | msdf_size=48 22 | allow_system_fallback=true 23 | force_autohinter=false 24 | hinting=1 25 | subpixel_positioning=1 26 | oversampling=0.0 27 | Fallbacks=null 28 | fallbacks=[] 29 | Compress=null 30 | compress=true 31 | preload=[] 32 | language_support={} 33 | script_support={} 34 | opentype_features={} 35 | -------------------------------------------------------------------------------- /resource/fonts/inter/Inter-VariableFont_slnt,wght.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JACKADUX/Application-Components/42861c0ada6148160223015db656de2325d3e3e3/resource/fonts/inter/Inter-VariableFont_slnt,wght.ttf -------------------------------------------------------------------------------- /resource/fonts/inter/Inter-VariableFont_slnt,wght.ttf.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="font_data_dynamic" 4 | type="FontFile" 5 | uid="uid://ctyf51c60qwe5" 6 | path="res://.godot/imported/Inter-VariableFont_slnt,wght.ttf-c3ddc25bdd13ddd1e5e07e1d063e567e.fontdata" 7 | 8 | [deps] 9 | 10 | source_file="res://resource/fonts/inter/Inter-VariableFont_slnt,wght.ttf" 11 | dest_files=["res://.godot/imported/Inter-VariableFont_slnt,wght.ttf-c3ddc25bdd13ddd1e5e07e1d063e567e.fontdata"] 12 | 13 | [params] 14 | 15 | Rendering=null 16 | antialiasing=1 17 | generate_mipmaps=false 18 | disable_embedded_bitmaps=true 19 | multichannel_signed_distance_field=false 20 | msdf_pixel_range=8 21 | msdf_size=48 22 | allow_system_fallback=true 23 | force_autohinter=false 24 | hinting=1 25 | subpixel_positioning=1 26 | oversampling=0.0 27 | Fallbacks=null 28 | fallbacks=[] 29 | Compress=null 30 | compress=true 31 | preload=[] 32 | language_support={} 33 | script_support={} 34 | opentype_features={} 35 | -------------------------------------------------------------------------------- /resource/fonts/inter/static/Inter-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JACKADUX/Application-Components/42861c0ada6148160223015db656de2325d3e3e3/resource/fonts/inter/static/Inter-Black.ttf -------------------------------------------------------------------------------- /resource/fonts/inter/static/Inter-Black.ttf.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="font_data_dynamic" 4 | type="FontFile" 5 | uid="uid://t6nfx86phmg5" 6 | path="res://.godot/imported/Inter-Black.ttf-fe957463a2a5f057e7c7bcdfc7f0eaa4.fontdata" 7 | 8 | [deps] 9 | 10 | source_file="res://resource/fonts/inter/static/Inter-Black.ttf" 11 | dest_files=["res://.godot/imported/Inter-Black.ttf-fe957463a2a5f057e7c7bcdfc7f0eaa4.fontdata"] 12 | 13 | [params] 14 | 15 | Rendering=null 16 | antialiasing=1 17 | generate_mipmaps=false 18 | disable_embedded_bitmaps=true 19 | multichannel_signed_distance_field=false 20 | msdf_pixel_range=8 21 | msdf_size=48 22 | allow_system_fallback=true 23 | force_autohinter=false 24 | hinting=1 25 | subpixel_positioning=1 26 | oversampling=0.0 27 | Fallbacks=null 28 | fallbacks=[] 29 | Compress=null 30 | compress=true 31 | preload=[] 32 | language_support={} 33 | script_support={} 34 | opentype_features={} 35 | -------------------------------------------------------------------------------- /resource/fonts/inter/static/Inter-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JACKADUX/Application-Components/42861c0ada6148160223015db656de2325d3e3e3/resource/fonts/inter/static/Inter-Bold.ttf -------------------------------------------------------------------------------- /resource/fonts/inter/static/Inter-Bold.ttf.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="font_data_dynamic" 4 | type="FontFile" 5 | uid="uid://duqu33td3g36m" 6 | path="res://.godot/imported/Inter-Bold.ttf-673f63452a2b537d605a15a9459bcf5e.fontdata" 7 | 8 | [deps] 9 | 10 | source_file="res://resource/fonts/inter/static/Inter-Bold.ttf" 11 | dest_files=["res://.godot/imported/Inter-Bold.ttf-673f63452a2b537d605a15a9459bcf5e.fontdata"] 12 | 13 | [params] 14 | 15 | Rendering=null 16 | antialiasing=1 17 | generate_mipmaps=false 18 | disable_embedded_bitmaps=true 19 | multichannel_signed_distance_field=false 20 | msdf_pixel_range=8 21 | msdf_size=48 22 | allow_system_fallback=true 23 | force_autohinter=false 24 | hinting=1 25 | subpixel_positioning=1 26 | oversampling=0.0 27 | Fallbacks=null 28 | fallbacks=[] 29 | Compress=null 30 | compress=true 31 | preload=[] 32 | language_support={} 33 | script_support={} 34 | opentype_features={} 35 | -------------------------------------------------------------------------------- /resource/fonts/inter/static/Inter-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JACKADUX/Application-Components/42861c0ada6148160223015db656de2325d3e3e3/resource/fonts/inter/static/Inter-ExtraBold.ttf -------------------------------------------------------------------------------- /resource/fonts/inter/static/Inter-ExtraBold.ttf.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="font_data_dynamic" 4 | type="FontFile" 5 | uid="uid://dhanx6kqtgyie" 6 | path="res://.godot/imported/Inter-ExtraBold.ttf-e34c0e4ec825b983b586ea1e4167a05e.fontdata" 7 | 8 | [deps] 9 | 10 | source_file="res://resource/fonts/inter/static/Inter-ExtraBold.ttf" 11 | dest_files=["res://.godot/imported/Inter-ExtraBold.ttf-e34c0e4ec825b983b586ea1e4167a05e.fontdata"] 12 | 13 | [params] 14 | 15 | Rendering=null 16 | antialiasing=1 17 | generate_mipmaps=false 18 | disable_embedded_bitmaps=true 19 | multichannel_signed_distance_field=false 20 | msdf_pixel_range=8 21 | msdf_size=48 22 | allow_system_fallback=true 23 | force_autohinter=false 24 | hinting=1 25 | subpixel_positioning=1 26 | oversampling=0.0 27 | Fallbacks=null 28 | fallbacks=[] 29 | Compress=null 30 | compress=true 31 | preload=[] 32 | language_support={} 33 | script_support={} 34 | opentype_features={} 35 | -------------------------------------------------------------------------------- /resource/fonts/inter/static/Inter-ExtraLight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JACKADUX/Application-Components/42861c0ada6148160223015db656de2325d3e3e3/resource/fonts/inter/static/Inter-ExtraLight.ttf -------------------------------------------------------------------------------- /resource/fonts/inter/static/Inter-ExtraLight.ttf.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="font_data_dynamic" 4 | type="FontFile" 5 | uid="uid://dcugiryvss0hu" 6 | path="res://.godot/imported/Inter-ExtraLight.ttf-ba4b21907159bbbda216bb99f2ff207b.fontdata" 7 | 8 | [deps] 9 | 10 | source_file="res://resource/fonts/inter/static/Inter-ExtraLight.ttf" 11 | dest_files=["res://.godot/imported/Inter-ExtraLight.ttf-ba4b21907159bbbda216bb99f2ff207b.fontdata"] 12 | 13 | [params] 14 | 15 | Rendering=null 16 | antialiasing=1 17 | generate_mipmaps=false 18 | disable_embedded_bitmaps=true 19 | multichannel_signed_distance_field=false 20 | msdf_pixel_range=8 21 | msdf_size=48 22 | allow_system_fallback=true 23 | force_autohinter=false 24 | hinting=1 25 | subpixel_positioning=1 26 | oversampling=0.0 27 | Fallbacks=null 28 | fallbacks=[] 29 | Compress=null 30 | compress=true 31 | preload=[] 32 | language_support={} 33 | script_support={} 34 | opentype_features={} 35 | -------------------------------------------------------------------------------- /resource/fonts/inter/static/Inter-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JACKADUX/Application-Components/42861c0ada6148160223015db656de2325d3e3e3/resource/fonts/inter/static/Inter-Light.ttf -------------------------------------------------------------------------------- /resource/fonts/inter/static/Inter-Light.ttf.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="font_data_dynamic" 4 | type="FontFile" 5 | uid="uid://m5vyang31b74" 6 | path="res://.godot/imported/Inter-Light.ttf-711a8301bcd90b8fafc931162678b603.fontdata" 7 | 8 | [deps] 9 | 10 | source_file="res://resource/fonts/inter/static/Inter-Light.ttf" 11 | dest_files=["res://.godot/imported/Inter-Light.ttf-711a8301bcd90b8fafc931162678b603.fontdata"] 12 | 13 | [params] 14 | 15 | Rendering=null 16 | antialiasing=1 17 | generate_mipmaps=false 18 | disable_embedded_bitmaps=true 19 | multichannel_signed_distance_field=false 20 | msdf_pixel_range=8 21 | msdf_size=48 22 | allow_system_fallback=true 23 | force_autohinter=false 24 | hinting=1 25 | subpixel_positioning=1 26 | oversampling=0.0 27 | Fallbacks=null 28 | fallbacks=[] 29 | Compress=null 30 | compress=true 31 | preload=[] 32 | language_support={} 33 | script_support={} 34 | opentype_features={} 35 | -------------------------------------------------------------------------------- /resource/fonts/inter/static/Inter-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JACKADUX/Application-Components/42861c0ada6148160223015db656de2325d3e3e3/resource/fonts/inter/static/Inter-Medium.ttf -------------------------------------------------------------------------------- /resource/fonts/inter/static/Inter-Medium.ttf.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="font_data_dynamic" 4 | type="FontFile" 5 | uid="uid://bqlxyr41804e8" 6 | path="res://.godot/imported/Inter-Medium.ttf-019fca267d26a75f3069243c7b6e0e27.fontdata" 7 | 8 | [deps] 9 | 10 | source_file="res://resource/fonts/inter/static/Inter-Medium.ttf" 11 | dest_files=["res://.godot/imported/Inter-Medium.ttf-019fca267d26a75f3069243c7b6e0e27.fontdata"] 12 | 13 | [params] 14 | 15 | Rendering=null 16 | antialiasing=1 17 | generate_mipmaps=false 18 | disable_embedded_bitmaps=true 19 | multichannel_signed_distance_field=false 20 | msdf_pixel_range=8 21 | msdf_size=48 22 | allow_system_fallback=true 23 | force_autohinter=false 24 | hinting=1 25 | subpixel_positioning=1 26 | oversampling=0.0 27 | Fallbacks=null 28 | fallbacks=[] 29 | Compress=null 30 | compress=true 31 | preload=[] 32 | language_support={} 33 | script_support={} 34 | opentype_features={} 35 | -------------------------------------------------------------------------------- /resource/fonts/inter/static/Inter-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JACKADUX/Application-Components/42861c0ada6148160223015db656de2325d3e3e3/resource/fonts/inter/static/Inter-Regular.ttf -------------------------------------------------------------------------------- /resource/fonts/inter/static/Inter-Regular.ttf.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="font_data_dynamic" 4 | type="FontFile" 5 | uid="uid://btvbh05cwd3k4" 6 | path="res://.godot/imported/Inter-Regular.ttf-7b371813e607368d4a3e5e7739effb25.fontdata" 7 | 8 | [deps] 9 | 10 | source_file="res://resource/fonts/inter/static/Inter-Regular.ttf" 11 | dest_files=["res://.godot/imported/Inter-Regular.ttf-7b371813e607368d4a3e5e7739effb25.fontdata"] 12 | 13 | [params] 14 | 15 | Rendering=null 16 | antialiasing=1 17 | generate_mipmaps=false 18 | disable_embedded_bitmaps=true 19 | multichannel_signed_distance_field=false 20 | msdf_pixel_range=8 21 | msdf_size=48 22 | allow_system_fallback=true 23 | force_autohinter=false 24 | hinting=1 25 | subpixel_positioning=1 26 | oversampling=0.0 27 | Fallbacks=null 28 | fallbacks=[] 29 | Compress=null 30 | compress=true 31 | preload=[] 32 | language_support={} 33 | script_support={} 34 | opentype_features={} 35 | -------------------------------------------------------------------------------- /resource/fonts/inter/static/Inter-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JACKADUX/Application-Components/42861c0ada6148160223015db656de2325d3e3e3/resource/fonts/inter/static/Inter-SemiBold.ttf -------------------------------------------------------------------------------- /resource/fonts/inter/static/Inter-SemiBold.ttf.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="font_data_dynamic" 4 | type="FontFile" 5 | uid="uid://caetpswfld825" 6 | path="res://.godot/imported/Inter-SemiBold.ttf-05a0e2e9e68a9721552e2f55a1847c36.fontdata" 7 | 8 | [deps] 9 | 10 | source_file="res://resource/fonts/inter/static/Inter-SemiBold.ttf" 11 | dest_files=["res://.godot/imported/Inter-SemiBold.ttf-05a0e2e9e68a9721552e2f55a1847c36.fontdata"] 12 | 13 | [params] 14 | 15 | Rendering=null 16 | antialiasing=1 17 | generate_mipmaps=false 18 | disable_embedded_bitmaps=true 19 | multichannel_signed_distance_field=false 20 | msdf_pixel_range=8 21 | msdf_size=48 22 | allow_system_fallback=true 23 | force_autohinter=false 24 | hinting=1 25 | subpixel_positioning=1 26 | oversampling=0.0 27 | Fallbacks=null 28 | fallbacks=[] 29 | Compress=null 30 | compress=true 31 | preload=[] 32 | language_support={} 33 | script_support={} 34 | opentype_features={} 35 | -------------------------------------------------------------------------------- /resource/fonts/inter/static/Inter-Thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JACKADUX/Application-Components/42861c0ada6148160223015db656de2325d3e3e3/resource/fonts/inter/static/Inter-Thin.ttf -------------------------------------------------------------------------------- /resource/fonts/inter/static/Inter-Thin.ttf.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="font_data_dynamic" 4 | type="FontFile" 5 | uid="uid://ccf218a1cw0ik" 6 | path="res://.godot/imported/Inter-Thin.ttf-2e7f9a51ee2b1ccd8f975a414ca821a9.fontdata" 7 | 8 | [deps] 9 | 10 | source_file="res://resource/fonts/inter/static/Inter-Thin.ttf" 11 | dest_files=["res://.godot/imported/Inter-Thin.ttf-2e7f9a51ee2b1ccd8f975a414ca821a9.fontdata"] 12 | 13 | [params] 14 | 15 | Rendering=null 16 | antialiasing=1 17 | generate_mipmaps=false 18 | disable_embedded_bitmaps=true 19 | multichannel_signed_distance_field=false 20 | msdf_pixel_range=8 21 | msdf_size=48 22 | allow_system_fallback=true 23 | force_autohinter=false 24 | hinting=1 25 | subpixel_positioning=1 26 | oversampling=0.0 27 | Fallbacks=null 28 | fallbacks=[] 29 | Compress=null 30 | compress=true 31 | preload=[] 32 | language_support={} 33 | script_support={} 34 | opentype_features={} 35 | -------------------------------------------------------------------------------- /resource/icons/Boghma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JACKADUX/Application-Components/42861c0ada6148160223015db656de2325d3e3e3/resource/icons/Boghma.png -------------------------------------------------------------------------------- /resource/icons/Boghma.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://cv3lk1pbm7kla" 6 | path="res://.godot/imported/Boghma.png-f315d4960b46f28fce0dbe3998f53b8e.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://resource/icons/Boghma.png" 14 | dest_files=["res://.godot/imported/Boghma.png-f315d4960b46f28fce0dbe3998f53b8e.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 | -------------------------------------------------------------------------------- /resource/icons/drag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JACKADUX/Application-Components/42861c0ada6148160223015db656de2325d3e3e3/resource/icons/drag.png -------------------------------------------------------------------------------- /resource/icons/drag.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://p00vrh0ps58s" 6 | path="res://.godot/imported/drag.png-fe3b89385e34641495c0b902273b2ed0.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://resource/icons/drag.png" 14 | dest_files=["res://.godot/imported/drag.png-fe3b89385e34641495c0b902273b2ed0.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 | -------------------------------------------------------------------------------- /resource/icons/godot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JACKADUX/Application-Components/42861c0ada6148160223015db656de2325d3e3e3/resource/icons/godot.png -------------------------------------------------------------------------------- /resource/icons/godot.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://baguolgtgf26d" 6 | path="res://.godot/imported/godot.png-756aa94b4634f7a605a18e9340d935b6.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://resource/icons/godot.png" 14 | dest_files=["res://.godot/imported/godot.png-756aa94b4634f7a605a18e9340d935b6.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 | -------------------------------------------------------------------------------- /resource/shader/ms_fill.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="VisualShader" load_steps=2 format=3 uid="uid://corhjembtpeld"] 2 | 3 | [sub_resource type="VisualShaderNodeColorParameter" id="VisualShaderNodeColorParameter_ti5v7"] 4 | parameter_name = "Fill" 5 | default_value_enabled = true 6 | 7 | [resource] 8 | code = "shader_type canvas_item; 9 | render_mode blend_mix; 10 | 11 | uniform vec4 Fill : source_color = vec4(1.000000, 1.000000, 1.000000, 1.000000); 12 | 13 | 14 | 15 | void fragment() { 16 | // ColorParameter:2 17 | vec4 n_out2p0 = Fill; 18 | 19 | 20 | // Output:0 21 | COLOR.rgb = vec3(n_out2p0.xyz); 22 | 23 | 24 | } 25 | " 26 | mode = 1 27 | flags/light_only = false 28 | nodes/fragment/0/position = Vector2(1000, 120) 29 | nodes/fragment/2/node = SubResource("VisualShaderNodeColorParameter_ti5v7") 30 | nodes/fragment/2/position = Vector2(400, 100) 31 | nodes/fragment/connections = PackedInt32Array(2, 0, 0, 0) 32 | -------------------------------------------------------------------------------- /tips.txt: -------------------------------------------------------------------------------- 1 | 替换exe图标,通过magick生成ico 2 | magick convert "C:\Users\Administrator\Desktop\tes\Boghma.png" -define icon:auto-resize=256,128,64,48,32,16 "C:\Users\Administrator\Desktop\tes\Boghma.ico" 3 | --------------------------------------------------------------------------------