├── .gitattributes ├── .gitignore ├── FACS ├── Editor │ ├── tes.FACSVis │ ├── tes.FACSVis.import │ ├── test.FACSVis │ └── test.FACSVis.import └── FACSManager.res ├── addons └── FancyControls │ ├── Controls │ ├── AnimatedBoxContainer │ │ ├── AnimatedBoxContainer.gd │ │ ├── AnimatedBoxContainer.gd.uid │ │ ├── AnimatedBoxContainer.png │ │ └── AnimatedBoxContainer.png.import │ ├── AnimatedContainer │ │ ├── AnimatedContainer.gd │ │ └── AnimatedContainer.gd.uid │ ├── AnimatedFromCenterRoundContainer │ │ ├── AnimatedFromCenterRoundContainer.gd │ │ └── AnimatedFromCenterRoundContainer.gd.uid │ ├── AnimatedGridContainer │ │ ├── AnimatedGridContainer.gd │ │ ├── AnimatedGridContainer.gd.uid │ │ ├── AnimatedGridContainer.png │ │ └── AnimatedGridContainer.png.import │ ├── AnimatedGridSlideInContainer │ │ ├── AnimatedGridSlideInContainer.gd │ │ ├── AnimatedGridSlideInContainer.gd.uid │ │ ├── AnimatedGridSlideInContainer.png │ │ └── AnimatedGridSlideInContainer.png.import │ ├── AnimatedItem │ │ ├── AnimatedItem.gd │ │ ├── AnimatedItem.gd.uid │ │ └── FancyAnimatedItem │ │ │ ├── FancyAnimatedItem.gd │ │ │ └── FancyAnimatedItem.gd.uid │ ├── AnimatedKeepContainer │ │ ├── AnimatedKeepContainer.gd │ │ └── AnimatedKeepContainer.gd.uid │ └── AnimatedRoundContainer │ │ ├── AnimatedRoundContainer.gd │ │ ├── AnimatedRoundContainer.gd.uid │ │ ├── AnimatedRoundContainer.png │ │ └── AnimatedRoundContainer.png.import │ ├── Example │ ├── Example.FACSVis │ ├── Example.FACSVis.import │ ├── ExampleGroup.gd │ ├── ExampleGroup.gd.uid │ ├── test_hover.gd │ ├── test_hover.gd.uid │ ├── testing.gd │ ├── testing.gd.uid │ └── testing.tscn │ ├── FACSManagerResource.gd │ ├── FACSManagerResource.gd.uid │ ├── FacsBinding.gd │ ├── FacsBinding.gd.uid │ ├── FacsLOGO.png │ ├── FacsLOGO.png.import │ ├── FancyControls.gd │ ├── FancyControls.gd.uid │ ├── GUI │ ├── Add.svg │ ├── Add.svg.import │ ├── AssetLib.svg │ ├── AssetLib.svg.import │ ├── GUItheme.tres │ ├── block │ │ ├── BlockColoring.gd │ │ ├── BlockColoring.gd.uid │ │ ├── BlockList.gd │ │ ├── BlockList.gd.uid │ │ ├── BlockListResource.gd │ │ ├── BlockListResource.gd.uid │ │ ├── BlockUI.gd │ │ ├── BlockUI.gd.uid │ │ ├── CodeBlockLogic.gd │ │ ├── CodeBlockLogic.gd.uid │ │ ├── CodeBlockParameters.gd │ │ ├── CodeBlockParameters.gd.uid │ │ ├── block_funcs.gd │ │ ├── block_funcs.gd.uid │ │ ├── block_script.gd │ │ ├── block_script.gd.uid │ │ ├── code_block_resource.gd │ │ └── code_block_resource.gd.uid │ ├── code_block_list.tres │ ├── codehighlight.tres │ ├── converters │ │ ├── json_visual_converter.gd │ │ ├── json_visual_converter.gd.uid │ │ ├── visual_node.gd │ │ ├── visual_node.gd.uid │ │ ├── visual_script_converter.gd │ │ └── visual_script_converter.gd.uid │ ├── example_animation_chains │ │ └── test_chain.json │ └── scene │ │ ├── 2d.res │ │ ├── ClassList.svg │ │ ├── ClassList.svg.import │ │ ├── CodeBox.gd │ │ ├── CodeBox.gd.uid │ │ ├── GraphNode.gd │ │ ├── GraphNode.gd.uid │ │ ├── GroupsBox.gd │ │ ├── GroupsBox.gd.uid │ │ ├── Remove.svg │ │ ├── Remove.svg.import │ │ ├── UndoRedoGraphManager.gd │ │ ├── UndoRedoGraphManager.gd.uid │ │ ├── control.tscn │ │ ├── gui_root_script.gd │ │ ├── gui_root_script.gd.uid │ │ ├── right_click_menu.gd │ │ ├── right_click_menu.gd.uid │ │ └── script.res │ ├── Importers │ ├── FACSGroupCompiler.gd │ ├── FACSGroupCompiler.gd.uid │ ├── FACSVisGroup.gd │ ├── FACSVisGroup.gd.uid │ ├── FACSVisImporter.gd │ ├── FACSVisImporter.gd.uid │ ├── FACSVisResource.gd │ ├── FACSVisResource.gd.uid │ ├── FacsVisGroupImporter.gd │ └── FacsVisGroupImporter.gd.uid │ ├── LICENSE │ ├── README.md │ └── plugin.cfg ├── icon.svg ├── icon.svg.import └── project.godot /.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 | -------------------------------------------------------------------------------- /FACS/Editor/tes.FACSVis: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RogerRandomDev/FancyControls/0857c63136dafbd05c85d05faeb2e75fd8885a74/FACS/Editor/tes.FACSVis -------------------------------------------------------------------------------- /FACS/Editor/tes.FACSVis.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="FACS.Visual" 4 | type="Resource" 5 | uid="uid://blma1gwxe52qg" 6 | path="res://.godot/imported/tes.FACSVis-eb57cff4734e746511564d3ed277e69a.res" 7 | 8 | [deps] 9 | 10 | source_file="res://FACS/Editor/tes.FACSVis" 11 | dest_files=["res://.godot/imported/tes.FACSVis-eb57cff4734e746511564d3ed277e69a.res"] 12 | 13 | [params] 14 | 15 | -------------------------------------------------------------------------------- /FACS/Editor/test.FACSVis: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RogerRandomDev/FancyControls/0857c63136dafbd05c85d05faeb2e75fd8885a74/FACS/Editor/test.FACSVis -------------------------------------------------------------------------------- /FACS/Editor/test.FACSVis.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="FACS.Visual" 4 | type="Resource" 5 | uid="uid://b8b0feaorc722" 6 | path="res://.godot/imported/test.FACSVis-bc266bc4cd50b648fae39f5575840976.res" 7 | 8 | [deps] 9 | 10 | source_file="res://FACS/Editor/test.FACSVis" 11 | dest_files=["res://.godot/imported/test.FACSVis-bc266bc4cd50b648fae39f5575840976.res"] 12 | 13 | [params] 14 | 15 | -------------------------------------------------------------------------------- /FACS/FACSManager.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RogerRandomDev/FancyControls/0857c63136dafbd05c85d05faeb2e75fd8885a74/FACS/FACSManager.res -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedBoxContainer/AnimatedBoxContainer.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | @icon("res://addons/FancyControls/Controls/AnimatedBoxContainer/AnimatedBoxContainer.png") 3 | extends AnimatedContainer 4 | class_name AnimatedBoxContainer 5 | 6 | @export_enum("Vertical","Horizontal") var box_direction:int=0: 7 | set(v): 8 | box_direction=v 9 | _notification(NOTIFICATION_RESIZED) 10 | 11 | 12 | 13 | 14 | 15 | func _update_spacings(animated:bool=true)->void: 16 | _update_start_positions() 17 | animated = animated and not Engine.is_editor_hint() 18 | if get_child_count()==0:return 19 | 20 | 21 | var nodes_to_space=get_children() 22 | var node_count=nodes_to_space.size() 23 | var available_space=(size.x if box_direction==1 else size.y) 24 | var extra_spacing = (available_space/node_count)*0.5 25 | 26 | for id in node_count: 27 | var target_position=get_target_position_for_item(id) 28 | if not (animate_spacing and animated): 29 | nodes_to_space[id].global_position=target_position 30 | nodes_to_space[id].targeted_position=target_position 31 | nodes_to_space[id].targeted_scale=Vector2.ONE 32 | #prevent an error from no tweened values 33 | 34 | 35 | func _editor_fit_contents()->void: 36 | var nodes_to_space=get_children() 37 | var node_count=nodes_to_space.size() 38 | var available_space=(size.x if box_direction==1 else size.y) 39 | var extra_spacing = (available_space/node_count)*0.5 40 | for id in node_count: 41 | var target_position=get_target_position_for_item(id) 42 | nodes_to_space[id].global_position=target_position 43 | nodes_to_space[id].scale=Vector2.ONE 44 | 45 | func get_target_position_for_item(id:int)->Vector2: 46 | var node_count=get_child_count() 47 | var available_space=(size.x if box_direction==1 else size.y) 48 | var spaced_position=((available_space/node_count)*id)+((available_space/node_count)*0.5) 49 | var target_position=global_position 50 | if box_direction==1: 51 | target_position.x+=spaced_position 52 | else: 53 | target_position.y+=spaced_position 54 | return target_position 55 | -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedBoxContainer/AnimatedBoxContainer.gd.uid: -------------------------------------------------------------------------------- 1 | uid://brvwggj2pxm6j 2 | -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedBoxContainer/AnimatedBoxContainer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RogerRandomDev/FancyControls/0857c63136dafbd05c85d05faeb2e75fd8885a74/addons/FancyControls/Controls/AnimatedBoxContainer/AnimatedBoxContainer.png -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedBoxContainer/AnimatedBoxContainer.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://b1l7ufniirudu" 6 | path="res://.godot/imported/AnimatedBoxContainer.png-61f02e8eed6fb3329599bdf1528926c8.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/FancyControls/Controls/AnimatedBoxContainer/AnimatedBoxContainer.png" 14 | dest_files=["res://.godot/imported/AnimatedBoxContainer.png-61f02e8eed6fb3329599bdf1528926c8.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedContainer/AnimatedContainer.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends Control 3 | class_name AnimatedContainer 4 | ## Base container class for handling all AnimatedContainer related needs. 5 | ## Stores the basic info for what is used by them all. 6 | 7 | 8 | ## updates the box contents whenever a child node is added 9 | @export var auto_update:bool=true 10 | 11 | ## if the contained items will animate or not 12 | @export var animate_spacing:bool=true 13 | 14 | 15 | ## the added space from the edge for all contained items 16 | @export var border_padding:Vector2=Vector2.ZERO: 17 | set(v): 18 | border_padding=v 19 | _notification(NOTIFICATION_RESIZED) 20 | 21 | @export_group("item functionality") 22 | ## the animation group script, can be done by hand as long as functions match the required inputs 23 | @export var animation_group:GDScript: 24 | set=set_animation_group 25 | 26 | ##the script that contains the functions that will be used by the contained [AnimatedItem] nodes 27 | @export var item_function_script:Script: 28 | set(v): 29 | item_function_script=v 30 | notify_property_list_changed() 31 | var _item_function_holder:Node=Node.new() 32 | 33 | var item_origin_positions:Array=[] 34 | 35 | var animations:RefCounted 36 | 37 | 38 | 39 | 40 | func set_animation_group(animation_group_new:GDScript): 41 | if animations==null:animations=RefCounted.new() 42 | animations.set_script(animation_group_new) 43 | if animation_group_new==animation_group:return 44 | animation_group=animation_group_new 45 | 46 | ## honestly this is just here for the one person who inevitably asks for it. 47 | ## also because the editor uses it to know what the function name is in the preview. 48 | func get_animation_list(): 49 | return animations.get_script().get_script_method_list().map(func(v):return v.name) 50 | ##because yes 51 | func play_animation(animation_name:String,_external_variables:Dictionary={})->void: 52 | clear_animations() 53 | animate_items_with_chain(animation_name,_external_variables) 54 | 55 | ##hmmm i love overwriting data 56 | func clear_animations()->void: 57 | for child in get_children(): 58 | if not child is FancyAnimatedItem:continue 59 | child=child as FancyAnimatedItem 60 | child.target_chains={"position":[],"rotation":[],"scale":[]} 61 | if child._tween_position: 62 | child._tween_position.kill() 63 | child._tween_position=null 64 | if child._tween_rotation: 65 | child._tween_rotation.kill() 66 | child._tween_rotation=null 67 | if child._tween_scale: 68 | child._tween_scale.kill() 69 | child._tween_scale=null 70 | 71 | 72 | func _ready(): 73 | if not Engine.is_editor_hint(): 74 | _item_function_holder.set_script(item_function_script) 75 | var is_auto=auto_update 76 | auto_update=false 77 | for child in get_children(): 78 | child.position=Vector2.ZERO 79 | self.add_child(child,false) 80 | auto_update=is_auto 81 | _attach_signal_links() 82 | _update_spacings.call_deferred(false) 83 | _update_start_positions(false) 84 | 85 | ##not sure how to optimize this but hopefully it comes eventually 86 | func _update_start_positions(recalculate:bool=true)->void: 87 | item_origin_positions.resize(get_child_count()) 88 | for i in get_child_count(): 89 | item_origin_positions[i]= get_child(i).global_position if not recalculate else get_target_position_for_item(i) 90 | 91 | 92 | func _update_spacings(animated:bool=true)->void:pass 93 | 94 | func _editor_fit_contents()->void:pass 95 | 96 | 97 | 98 | ## Overriding the default to allow some custom stuff to be handled. 99 | ## If set to an internal child, it will be stored normally and not as an item to hold 100 | func add_child(child:Node,internal:bool=false,internal_mode:Node.InternalMode=Node.INTERNAL_MODE_DISABLED)->void: 101 | if child is AnimatedItem or Engine.is_editor_hint() or internal: 102 | super.add_child(child,internal,internal_mode) 103 | if Engine.is_editor_hint(): 104 | _editor_fit_contents() 105 | return 106 | var child_holder=FancyAnimatedItem.new(self,child) 107 | if not Engine.is_editor_hint():attach_signals_to_item(child_holder) 108 | 109 | super.add_child(child_holder,internal,internal_mode) 110 | child_holder.owner=get_tree().get_edited_scene_root() 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | ## Basically just get_child() 123 | func get_item(item_id:int=-1)->AnimatedItem: 124 | if item_id<0 or item_id>get_child_count()-1:return null 125 | return get_child(item_id) 126 | 127 | ## Specialized version of [method add_child] that allows the item added to be reparented 128 | ## if it was already connected to anything. [param animate_position] will make the item 129 | ## animate itself from where it was to where it should be. 130 | func add_item(item:AnimatedItem,animate_position:bool=false)->void: 131 | if animate_position: 132 | var start_position=item.global_position 133 | #creates new version of the item to clear the old one out and ignore any tweens on it 134 | if item.get_parent()!=null: 135 | item.reparent(self,false) 136 | else: 137 | add_child(item) 138 | 139 | var ind=get_children().find(item) 140 | var child_position=get_target_position_for_item(ind) 141 | animate_item_from_position.call_deferred(item,start_position,child_position) 142 | else: 143 | add_child(item) 144 | attach_signals_to_item(item) 145 | 146 | 147 | ## Swaps the items at position [param id_1] and [param id_2]. 148 | ## Is animated if [member animate_spacing] is set to true. 149 | func swap_items(id_1:int,id_2:int)->void: 150 | if not(get_child_count()>id_1 and get_child_count()>id_2 and id_1>=0 and id_2>=0):return 151 | var first:AnimatedItem=get_child(id_1) 152 | var second:AnimatedItem=get_child(id_2) 153 | move_child(first,id_2) 154 | move_child(second,id_1) 155 | 156 | 157 | ## used to make the items move forwards by putting the last item in the first item position 158 | func shift_items_forward()->void: 159 | if get_child_count()<1:return 160 | move_child(get_child(get_child_count()-1),0) 161 | ## reverse of [method shift_items_forward] where it pushes items from the first spot to the last 162 | ## to let them cycle 163 | func shift_items_back()->void: 164 | if get_child_count()<1:return 165 | move_child(get_child(0),get_child_count()-1) 166 | 167 | 168 | 169 | ## Makes [AnimatedItem] move from the [param from_position] to [param to_position] 170 | func animate_item_from_position(item:AnimatedItem,from_position:Vector2,to_position:Vector2)->void: 171 | item.global_position=from_position 172 | item.targeted_position=to_position 173 | 174 | ## Used by containers based on this for getting where the [AnimatedItem] nodes place themselves 175 | func get_target_position_for_item(id:int)->Vector2:return Vector2.ZERO 176 | 177 | 178 | func animate_items_with_chain(chain_name:String,_external_variables:Dictionary={})->void: 179 | var scr=animations 180 | var container_data={ 181 | "size":size, 182 | "global_position":global_position, 183 | "item_origins":item_origin_positions, 184 | "rotation":rotation 185 | } 186 | #var bound_call:Callable= 187 | for i in get_child_count(): 188 | var child=get_child(i) 189 | scr.call(chain_name,child,i,get_child_count(),container_data,_external_variables) 190 | 191 | #if response == null:continue 192 | #this code is bad. 193 | #this is not high in my list of priorities yet. 194 | #probably going to update the editor itself to compile the calls to chain directly. 195 | #would save on everything. 196 | #for p in response.Positions:child.chain_action(0,p.get("goal"),p.get("duration"),p.get("tween_type")) 197 | #for p in response.Rotations:child.chain_action(1,p.get("goal"),p.get("duration"),p.get("tween_type")) 198 | #for p in response.Scales:child.chain_action(2,p.get("goal"),p.get("duration"),p.get("tween_type")) 199 | 200 | 201 | 202 | 203 | 204 | 205 | #used to handle some events that are emitted 206 | func _notification(what): 207 | match what: 208 | NOTIFICATION_CHILD_ORDER_CHANGED: 209 | #fancy stuff going on here. 210 | #made with this so you can stop it if you dont want it 211 | if auto_update: 212 | if Engine.is_editor_hint():_editor_fit_contents() 213 | else:_update_spacings.call_deferred() 214 | NOTIFICATION_RESIZED: 215 | if auto_update: 216 | if Engine.is_editor_hint():_editor_fit_contents() 217 | else:_update_spacings.call_deferred() 218 | 219 | 220 | ##the actions linked to the [AnimatedItem] nodes in the containers. 221 | const item_actions:Array=[ 222 | &"hovered", 223 | &"unhovered", 224 | &"focused", 225 | &"unfocused", 226 | &"input" 227 | ] 228 | var _hovered:StringName=&"" 229 | var _unhovered:StringName=&"" 230 | var _focused:StringName=&"" 231 | var _unfocused:StringName=&"" 232 | var _input:StringName=&"" 233 | 234 | 235 | 236 | func _get_property_list(): 237 | var result=[] 238 | 239 | var script_funcs := "" 240 | if item_function_script != null and item_function_script is Script: 241 | script_funcs = ",".join(item_function_script.get_script_method_list().map(func(x): return x[&"name"])) 242 | result.append_array( 243 | item_actions.map( 244 | func (x): return { 245 | &"name": "_"+x, 246 | &"type": TYPE_STRING_NAME, 247 | &"usage": PROPERTY_USAGE_DEFAULT, 248 | &"hint": PROPERTY_HINT_ENUM_SUGGESTION, 249 | &"hint_string": script_funcs, 250 | } 251 | ) 252 | ) 253 | return result 254 | #internal only, this handles linking the properties for signals to the functions being called 255 | func _attach_signal_links()->void: 256 | if not (item_function_script is Script and item_function_script != null):return 257 | #loop all children and apply the linking to the items 258 | for item in get_children(): 259 | if not item is AnimatedItem:continue 260 | attach_signals_to_item(item) 261 | ##used internally to connect the signal functions to the [AnimatedItem] nodes 262 | func attach_signals_to_item(item:AnimatedItem)->void: 263 | for sig in item.get_signal_list(): 264 | if not ["mouse_entered","mouse_exited","focus_entered","focus_exited","gui_input"].has(sig.name):continue 265 | for con in item.get_signal_connection_list(sig.name): 266 | item.disconnect(sig.name,con.callable) 267 | if _hovered!=&"":item.mouse_entered.connect(_item_function_holder.call.bind(_hovered,item)) 268 | if _unhovered!=&"":item.mouse_exited.connect(_item_function_holder.call.bind(_unhovered,item)) 269 | if _focused!=&"":item.focus_entered.connect(_item_function_holder.call.bind(_focused,item)) 270 | if _unfocused!=&"":item.focus_exited.connect(_item_function_holder.call.bind(_unfocused,item)) 271 | if _input!=&"":item.gui_input.connect(_item_function_holder.call.bind(_input,item)) 272 | -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedContainer/AnimatedContainer.gd.uid: -------------------------------------------------------------------------------- 1 | uid://bw4numnsis6fi 2 | -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedFromCenterRoundContainer/AnimatedFromCenterRoundContainer.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends AnimatedRoundContainer 3 | class_name AnimatedFromCenterRoundContainer 4 | 5 | @export var active:bool=false: 6 | set(v): 7 | active=v 8 | _notification(NOTIFICATION_RESIZED) 9 | 10 | 11 | 12 | 13 | 14 | 15 | func get_target_position_for_item(id:int)->Vector2: 16 | var node_count=get_child_count() 17 | var available_space=(size.x if box_direction==1 else size.y) 18 | var spaced_position=Vector2(0,-1).rotated((id/float(node_count))*PI*2*(box_direction*2-1)+initial_rotation_degrees)*float(active) 19 | var target_position=(spaced_position*(size*0.5-border_padding)+size*0.5)+global_position 20 | return target_position 21 | -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedFromCenterRoundContainer/AnimatedFromCenterRoundContainer.gd.uid: -------------------------------------------------------------------------------- 1 | uid://meu2sn4owjwk 2 | -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedGridContainer/AnimatedGridContainer.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | @icon("res://addons/FancyControls/Controls/AnimatedGridContainer/AnimatedGridContainer.png") 3 | extends AnimatedContainer 4 | class_name AnimatedGridContainer 5 | ## Grid container based on the [AnimatedContainer] for handling a grid with a known width or height. 6 | 7 | ## If the container grows vertically or horizontally 8 | @export_enum("Vertical","Horizontal") var expand_direction:int=0: 9 | set(v): 10 | expand_direction=v 11 | _notification(NOTIFICATION_RESIZED) 12 | ## Spacing between item middles. If items overlap remember the spacing doesn't account for item size. 13 | ## You have to account for that in the spacing as well. 14 | @export var item_spacing:Vector2=Vector2.ZERO: 15 | set(v): 16 | item_spacing=v 17 | _notification(NOTIFICATION_RESIZED) 18 | 19 | 20 | func _update_spacings(animated:bool=true)->void: 21 | 22 | animated = animated and not Engine.is_editor_hint() 23 | if get_child_count()==0 or Engine.is_editor_hint():return 24 | 25 | var nodes_to_space=get_children() 26 | var node_count=nodes_to_space.size() 27 | var available_space=size*0.5 28 | 29 | for id in node_count: 30 | var target_position=get_target_position_for_item(id)+nodes_to_space[id].attached_item.size*0.5 31 | if not (animate_spacing and animated): 32 | nodes_to_space[id].global_position=target_position 33 | nodes_to_space[id].targeted_position=target_position 34 | 35 | #prevent an error from no tweened values 36 | 37 | 38 | func _editor_fit_contents()->void: 39 | var nodes_to_space=get_children() 40 | var node_count=nodes_to_space.size() 41 | var offset=size*0.5 42 | for id in node_count: 43 | var target_position=get_target_position_for_item(id) 44 | nodes_to_space[id].global_position=target_position 45 | nodes_to_space[id].scale=Vector2.ONE 46 | 47 | 48 | ## returns the vector2 for where the given item id is placed. 49 | ## only returns correctly assuming [param id] is already within the items in the container. 50 | func get_target_position_for_item(id:int)->Vector2: 51 | if item_spacing.x==0 or item_spacing.y==0 or size.x==0 or size.y==0:return Vector2.ZERO 52 | var node_count=get_child_count() 53 | var available_space=(size.x-border_padding.x*2 if expand_direction==0 else size.y-border_padding.y*2) 54 | var space_per_item=Vector2i((size-border_padding*2)/item_spacing) 55 | var used_item_space=(space_per_item.x if expand_direction==0 else space_per_item.y) 56 | var second_item_space=(space_per_item.y if expand_direction==0 else space_per_item.x) 57 | var target_position=Vector2( 58 | (available_space/used_item_space)*(id%used_item_space), 59 | int(id/used_item_space)*(item_spacing.y if expand_direction==0 else item_spacing.x) 60 | ) 61 | if expand_direction==1: 62 | target_position=Vector2(target_position.y,target_position.x) 63 | target_position=(target_position+border_padding)+global_position 64 | return target_position 65 | -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedGridContainer/AnimatedGridContainer.gd.uid: -------------------------------------------------------------------------------- 1 | uid://c03kq8pkcd07e 2 | -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedGridContainer/AnimatedGridContainer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RogerRandomDev/FancyControls/0857c63136dafbd05c85d05faeb2e75fd8885a74/addons/FancyControls/Controls/AnimatedGridContainer/AnimatedGridContainer.png -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedGridContainer/AnimatedGridContainer.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://cyn2q58et8vux" 6 | path="res://.godot/imported/AnimatedGridContainer.png-675f99f8e13cde698f72f3611c317b9a.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/FancyControls/Controls/AnimatedGridContainer/AnimatedGridContainer.png" 14 | dest_files=["res://.godot/imported/AnimatedGridContainer.png-675f99f8e13cde698f72f3611c317b9a.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedGridSlideInContainer/AnimatedGridSlideInContainer.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | @icon("res://addons/FancyControls/Controls/AnimatedGridSlideInContainer/AnimatedGridSlideInContainer.png") 3 | extends AnimatedGridContainer 4 | class_name AnimatedGridSlideInContainer 5 | 6 | @export var slide_from_direction:Vector2=Vector2.UP: 7 | set(v): 8 | slide_from_direction=v 9 | _notification(NOTIFICATION_RESIZED) 10 | 11 | @export var active:bool=false: 12 | set(v): 13 | active=v 14 | _notification(NOTIFICATION_RESIZED) 15 | 16 | 17 | 18 | 19 | 20 | ## returns the vector2 for where the given item id is placed. 21 | ## only returns correctly assuming [param id] is already within the items in the container. 22 | func get_target_position_for_item(id:int)->Vector2: 23 | if item_spacing.x==0 or item_spacing.y==0 or size.x==0 or size.y==0:return Vector2.ZERO 24 | var node_count=get_child_count() 25 | var available_space=(size.x-border_padding.x*2 if expand_direction==0 else size.y-border_padding.y*2) 26 | var space_per_item=Vector2i((size-border_padding*2)/item_spacing) 27 | var used_item_space=(space_per_item.x if expand_direction==0 else space_per_item.y) 28 | var second_item_space=(space_per_item.y if expand_direction==0 else space_per_item.x) 29 | var target_position=Vector2( 30 | (available_space/used_item_space)*(id%used_item_space), 31 | int(id/used_item_space)*(item_spacing.y if expand_direction==0 else item_spacing.x) 32 | ) 33 | if expand_direction==1: 34 | target_position=Vector2(target_position.y,target_position.x) 35 | target_position=(target_position+border_padding)+global_position+(size*slide_from_direction*float(!active)) 36 | return target_position 37 | -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedGridSlideInContainer/AnimatedGridSlideInContainer.gd.uid: -------------------------------------------------------------------------------- 1 | uid://c1c16msvvybt6 2 | -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedGridSlideInContainer/AnimatedGridSlideInContainer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RogerRandomDev/FancyControls/0857c63136dafbd05c85d05faeb2e75fd8885a74/addons/FancyControls/Controls/AnimatedGridSlideInContainer/AnimatedGridSlideInContainer.png -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedGridSlideInContainer/AnimatedGridSlideInContainer.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://d3cx2om85ceo8" 6 | path="res://.godot/imported/AnimatedGridSlideInContainer.png-51e1a17821d3a6d4757505c542887cfa.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/FancyControls/Controls/AnimatedGridSlideInContainer/AnimatedGridSlideInContainer.png" 14 | dest_files=["res://.godot/imported/AnimatedGridSlideInContainer.png-51e1a17821d3a6d4757505c542887cfa.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedItem/AnimatedItem.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends Control 3 | class_name AnimatedItem 4 | ## The base item used by [AnimatedContainer] nodes and their subtypes. 5 | ## Contains the managing systems for its animating. 6 | signal tweens_synced 7 | 8 | 9 | ## The node that is contained within this [AnimatedItem] 10 | var attached_item:Node 11 | ## The node that contains this [AnimatedItem]. 12 | ## This node has to be a [AnimatedContainer] or one of its subtypes. 13 | var connected_control:Node 14 | 15 | var manual_transformations:Control=Control.new() 16 | 17 | var _pos_relative:bool=false 18 | var _pos_travel_time:float=-1.0 19 | var _rot_travel_time:float=-1.0 20 | var _scale_travel_time:float=-1.0 21 | var _pos_trans:int=0 22 | var _rot_trans:int=0 23 | var _scale_trans:int=0 24 | 25 | var manual_step:bool=false 26 | ## setting it moves it based on the size of the container 0-1 being from container corner to container size 27 | ## also returns the 0-1 variation of position 28 | var relative_position:Vector2: 29 | set(v): 30 | position=v*get_parent_control().size 31 | get:return position/get_parent_control().size 32 | 33 | 34 | ## The position to animate the [AnimatedItem] to from the current position. 35 | ## Automatically animates when changed. 36 | var targeted_position: 37 | set(v): 38 | 39 | assert(v is Vector2) 40 | #if Engine.is_editor_hint():return 41 | if _pos_travel_time==-1:_pos_travel_time=get_pos_travel(v) 42 | targeted_position=v 43 | if is_inside_tree(): 44 | var step_mode:bool=false 45 | if _tween_position:_tween_position.kill() 46 | _tween_position=create_tween() 47 | _tween_position.set_trans(_pos_trans) 48 | var pos_type='relative_position' if _pos_relative else 'global_position' 49 | 50 | _tween_position.tween_property(self,pos_type,targeted_position,_pos_travel_time) 51 | _tween_position.finished.connect(_param_tween_finished.bind("Pos")) 52 | _pos_travel_time=-1.0 53 | _pos_trans=Tween.TRANS_LINEAR 54 | if manual_step:_tween_position.pause() 55 | else: 56 | global_position=targeted_position 57 | ## The rotation to animate the [AnimatedItem] to from the current rotation. 58 | ## Automatically animates when changed. 59 | var targeted_rotation=0.0: 60 | set(v): 61 | assert(v is float) 62 | #if Engine.is_editor_hint():return 63 | 64 | if _rot_travel_time==-1:_rot_travel_time=get_rot_travel(v) 65 | 66 | targeted_rotation=v 67 | if is_inside_tree(): 68 | if _tween_rotation:_tween_rotation.kill() 69 | _tween_rotation=create_tween() 70 | _tween_rotation.set_trans(_rot_trans) 71 | #this is to make sure it takes the shortest path it can 72 | 73 | _tween_rotation.tween_property(self,'rotation',targeted_rotation,_rot_travel_time) 74 | _tween_rotation.finished.connect(_param_tween_finished.bind("Rot")) 75 | _rot_travel_time=-1.0 76 | _rot_trans=Tween.TRANS_LINEAR 77 | if manual_step:_tween_rotation.pause() 78 | #_tween_rotation.tween_property(self,'rotation',targeted_rotation,0.25) 79 | else: 80 | rotation=targeted_rotation 81 | 82 | ## The scale to animate the [AnimatedItem] to from the current scale. 83 | ## Automatically animates when changed. 84 | var targeted_scale=Vector2.ONE: 85 | set(v): 86 | assert(v is Vector2) 87 | #if Engine.is_editor_hint():return 88 | if _scale_travel_time==-1:_scale_travel_time=get_scale_travel(v) 89 | 90 | targeted_scale=v 91 | if is_inside_tree(): 92 | if _tween_scale:_tween_scale.kill() 93 | _tween_scale=create_tween() 94 | _tween_scale.set_trans(_scale_trans) 95 | #this is to make sure it takes the shortest path it can 96 | #targeted_rotation=-(targeted_rotation-PI) 97 | 98 | _tween_scale.tween_property(self,'scale',targeted_scale,_scale_travel_time) 99 | _tween_scale.finished.connect(_param_tween_finished.bind("Scl")) 100 | _scale_travel_time=-1.0 101 | _scale_trans=Tween.TRANS_LINEAR 102 | if manual_step:_tween_scale.pause() 103 | else: 104 | scale=targeted_scale 105 | 106 | ##change this value to adjust how fast scaling occurs 107 | var scale_rate_per_second:float=16.0 108 | ##change this value to adjust how fast the item moves to the chosen location when it is changed 109 | var pixels_per_second:float=4608.0 110 | 111 | 112 | var _tween_position:Tween 113 | var _tween_rotation:Tween 114 | var _tween_scale:Tween 115 | 116 | var _tween_manual_position:Tween 117 | var _tween_manual_rotation:Tween 118 | var _tween_manual_scale:Tween 119 | 120 | func set_stacked_scale(new_scale:Vector2,over_duration:float=0.0,tween_type:Tween.TransitionType=Tween.TRANS_LINEAR)->void: 121 | if _tween_manual_scale!=null: 122 | _tween_manual_scale.kill() 123 | _tween_manual_scale=manual_transformations.create_tween() 124 | _tween_manual_scale.tween_property(manual_transformations,"scale",new_scale,over_duration).set_trans(tween_type) 125 | func set_stacked_position(new_position:Vector2,over_duration:float=0.0,tween_type:Tween.TransitionType=Tween.TRANS_LINEAR)->void: 126 | if _tween_manual_position!=null: 127 | _tween_manual_position.kill() 128 | _tween_manual_position=manual_transformations.create_tween() 129 | _tween_manual_position.tween_property(manual_transformations,"position",new_position,over_duration).set_trans(tween_type) 130 | func set_stacked_rotation(new_rotation:float,over_duration:float=0.0,tween_type:Tween.TransitionType=Tween.TRANS_LINEAR)->void: 131 | if _tween_manual_rotation!=null: 132 | _tween_manual_rotation.kill() 133 | _tween_manual_rotation=manual_transformations.create_tween() 134 | _tween_manual_rotation.tween_property(manual_transformations,"rotation",new_rotation,over_duration).set_trans(tween_type) 135 | 136 | func _get(property): 137 | if property.begins_with("stacked"): 138 | return manual_transformations.get(property.trim_prefix('stacked_')) 139 | 140 | func _set(property, value): 141 | if property.begins_with("stacked"): 142 | call("set_%s"%property,value) 143 | return true 144 | return false 145 | 146 | 147 | 148 | 149 | 150 | func get_pos_travel(to)->float: 151 | var travel_distance=(to-global_position).length() 152 | return sqrt(travel_distance/pixels_per_second) 153 | func get_rot_travel(to)->float: 154 | var travel_distance=abs(angle_difference(to,rotation)) 155 | if abs(targeted_rotation)float: 159 | var travel_distance = (scale-to).length() 160 | return sqrt(travel_distance/scale_rate_per_second) 161 | 162 | func _init(connected_to:Node=null,attached_to:Node=null): 163 | #cause yes 164 | add_child(manual_transformations) 165 | for child in get_children():if not child==manual_transformations:child.reparent(manual_transformations,false) 166 | 167 | #this line is so pre-build ones don't break when loading 168 | if connected_to==null and attached_to==null: 169 | return 170 | assert(attached_to is Control,"Node Attached to an Animated Container Item is not a Control") 171 | 172 | connected_control=connected_control 173 | attached_item=attached_to 174 | 175 | 176 | #attaches item to manual_transformations as a child 177 | if attached_item!=null: 178 | if attached_item.get_parent(): 179 | attached_item.reparent(manual_transformations,false) 180 | else: 181 | manual_transformations.add_child(attached_item) 182 | (attached_item as Control).resized.connect(attached_item_size_changed) 183 | attached_item_size_changed() 184 | 185 | size_flags_horizontal=Control.SIZE_SHRINK_CENTER 186 | size_flags_vertical=Control.SIZE_SHRINK_CENTER 187 | 188 | position.x=connected_to.size.x*0.5 189 | position.y=connected_to.size.y*0.5 190 | 191 | child_exiting_tree.connect(check_if_needed) 192 | bind_interaction_signals() 193 | 194 | 195 | 196 | ##used to allow syncing up the animations 197 | func _param_tween_finished(param_name)->void: 198 | match param_name: 199 | "Pos":if _tween_position: 200 | _tween_position.kill() 201 | _tween_position=null 202 | "Rot":if _tween_rotation: 203 | _tween_rotation.kill() 204 | _tween_rotation=null 205 | "Scl":if _tween_scale: 206 | _tween_scale.kill() 207 | _tween_scale=null 208 | 209 | if( 210 | (_tween_position==null or not _tween_position.is_valid()) and 211 | (_tween_rotation==null or not _tween_rotation.is_valid()) and 212 | (_tween_scale==null or not _tween_scale.is_valid()) 213 | ): 214 | 215 | emit_signal.call_deferred("tweens_synced") 216 | 217 | 218 | 219 | ## binds the signals from the [member attached_item] to emit from self to allow the [member connected_control] 220 | ## to recieve them and process them accordingly based on its [member AnimatedContainer.item_actions] 221 | func bind_interaction_signals()->void: 222 | if attached_item == null:return 223 | attached_item.mouse_entered.connect(emit_signal.bind("mouse_entered")) 224 | attached_item.mouse_exited.connect(emit_signal.bind("mouse_exited")) 225 | attached_item.focus_entered.connect(emit_signal.bind("focus_entered")) 226 | attached_item.focus_exited.connect(emit_signal.bind("focus_exited")) 227 | 228 | 229 | func _enter_tree(): 230 | targeted_position=global_position 231 | 232 | 233 | ## checks that it still has an attached item in the tree 234 | ## and frees itself if it finds none 235 | func check_if_needed(value)->void: 236 | if value==attached_item and (value==null or value.is_queued_for_deletion()): 237 | queue_free() 238 | 239 | 240 | ## emited when the item contained changes size. 241 | ## recenters the contained item in self 242 | func attached_item_size_changed()->void: 243 | if attached_item==null:return 244 | attached_item.position=-attached_item.size*0.5 245 | attached_item.pivot_offset=attached_item.size*0.5 246 | 247 | func get_content_meta(meta_name:String,default)->Variant: 248 | if has_meta(meta_name):return get_meta(meta_name,default) 249 | return connected_control.get_meta(meta_name,default) 250 | -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedItem/AnimatedItem.gd.uid: -------------------------------------------------------------------------------- 1 | uid://bvsnt7l77j0pw 2 | -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedItem/FancyAnimatedItem/FancyAnimatedItem.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends AnimatedItem 3 | class_name FancyAnimatedItem 4 | ## Fancy version of [AnimatedItem]. Uses arrays and specified times and (optionally) tween type for each value to move towards 5 | 6 | 7 | var target_chains:Dictionary={ 8 | "position":[], 9 | "rotation":[], 10 | "scale":[] 11 | } 12 | 13 | enum AnimatableTypes{ 14 | POSITION, 15 | ROTATION, 16 | SCALE 17 | } 18 | 19 | ##fills the duty of syncing all action chains 20 | func sync_chains()->void: 21 | chain_action(0,Vector2.ZERO,0,-9) 22 | chain_action(1,0.0,0,-9) 23 | chain_action(2,Vector2.ZERO,0,-9) 24 | 25 | ##utterly rediculous how this works. 26 | ##not that it's bad just could be better. 27 | func chain_action(on_type:AnimatableTypes,target:Variant,duration:float=-1,tween_type:Tween.TransitionType=Tween.TRANS_LINEAR,relative:bool=false)->void: 28 | match on_type: 29 | AnimatableTypes.POSITION: 30 | assert(target is Vector2) 31 | target_chains.position.push_back({ 32 | "goal":target, 33 | "duration":duration, 34 | "tween":tween_type, 35 | "relative":relative 36 | }) 37 | if _tween_position==null||not _tween_position.is_valid():_target_chains_updated("position") 38 | 39 | AnimatableTypes.ROTATION: 40 | assert(target is float or target is int) 41 | target=float(target) 42 | target_chains.rotation.push_back({ 43 | "goal":target, 44 | "duration":duration, 45 | "tween":tween_type 46 | }) 47 | if _tween_rotation==null||not _tween_position.is_valid():_target_chains_updated("rotation") 48 | 49 | AnimatableTypes.SCALE: 50 | assert(target is Vector2) 51 | target_chains.scale.push_back({ 52 | "goal":target, 53 | "duration":duration, 54 | "tween":tween_type 55 | }) 56 | if _tween_scale==null||not _tween_position.is_valid():_target_chains_updated("scale") 57 | 58 | 59 | 60 | 61 | 62 | 63 | ##handles running the chain when it is added 64 | func _target_chains_updated(updated_set:String)->void: 65 | #if Engine.is_editor_hint():return 66 | match updated_set: 67 | "position": 68 | var front_index=target_chains["position"].pop_front() 69 | if front_index==null:return 70 | #represents syncing 71 | if front_index.tween==-9: 72 | await tweens_synced 73 | _target_chains_updated("position") 74 | return 75 | 76 | _pos_trans=front_index.tween 77 | _pos_travel_time=front_index.duration 78 | _pos_relative=front_index.relative 79 | targeted_position=front_index.goal 80 | #so if the animator isnt creating a tween it just 81 | if _tween_position!=null:_tween_position.finished.connect(_target_chains_updated.bind("position")) 82 | else:_target_chains_updated("position") 83 | "rotation": 84 | var front_index=target_chains["rotation"].pop_front() 85 | if front_index==null:return 86 | #represents syncing 87 | if front_index.tween==-9: 88 | await tweens_synced 89 | _target_chains_updated("rotation") 90 | return 91 | _rot_trans=front_index.tween 92 | _rot_travel_time=front_index.duration 93 | targeted_rotation=front_index.goal 94 | await get_tree().process_frame 95 | #i actually dont remember what this comment was for, i was sleep deprived making this work. 96 | #so if the animator isnt creating a tween it just 97 | if _tween_rotation!=null: 98 | #_tween_rotation.set_trans(front_index.tween) 99 | _tween_rotation.finished.connect(_target_chains_updated.bind("rotation")) 100 | else: 101 | _target_chains_updated("rotation") 102 | "scale": 103 | var front_index=target_chains["scale"].pop_front() 104 | if front_index==null:return 105 | #represents syncing 106 | if front_index.tween==-9: 107 | await tweens_synced 108 | _target_chains_updated("scale") 109 | return 110 | 111 | _scale_trans=front_index.tween 112 | _scale_travel_time=front_index.duration 113 | targeted_scale=front_index.goal 114 | await get_tree().process_frame 115 | #so if the animator isnt creating a tween it just 116 | if _tween_scale!=null: 117 | #_tween_scale.set_trans(front_index.tween) 118 | _tween_scale.finished.connect(_target_chains_updated.bind("scale")) 119 | else:_target_chains_updated("scale") 120 | 121 | 122 | 123 | 124 | 125 | #region editor help and misc for managing it outside/inside the game 126 | #an absolute mess 127 | #do not touch this please it is very sensitive and will cry. 128 | 129 | func _set(property, value): 130 | if property.contains("count"): 131 | target_chains[property.trim_suffix("_count")].resize(value) 132 | var null_count=target_chains[property.trim_suffix("_count")].count(null) 133 | while target_chains[property.trim_suffix("_count")].find(null)>-1: 134 | var nulls=target_chains[property.trim_suffix("_count")].find(null) 135 | match property: 136 | "position_count": 137 | target_chains[property.trim_suffix("_count")][nulls]={ 138 | "goal":Vector2.ZERO, 139 | "duration":-1.0, 140 | "tween":Tween.TRANS_LINEAR 141 | } 142 | "scale_count": 143 | target_chains[property.trim_suffix("_count")][nulls]={ 144 | "goal":Vector2.ONE, 145 | "duration":-1.0, 146 | "tween":Tween.TRANS_LINEAR 147 | } 148 | "rotation_count": 149 | target_chains[property.trim_suffix("_count")][nulls]={ 150 | "goal":0.0, 151 | "duration":-1.0, 152 | "tween":Tween.TRANS_LINEAR 153 | } 154 | notify_property_list_changed() 155 | if property.contains("/") and (property.contains("position_") or property.contains("rotation_") or property.contains("scale_")): 156 | 157 | var type=property.split("_")[0] 158 | var number=int(property.trim_prefix(type+"_").split("/")[0]) 159 | target_chains[type][number][property.split("/")[1]]=value 160 | notify_property_list_changed() 161 | 162 | 163 | 164 | func _get(property): 165 | if property.contains("count"): 166 | return target_chains[property.trim_suffix("_count")].size() 167 | 168 | if property.contains("targets"): 169 | return target_chains[property.trim_suffix("_targets")] 170 | if property.contains("/") and (property.contains("position_") or property.contains("rotation_") or property.contains("scale_")): 171 | var type=property.split("_")[0] 172 | var number=int(property.trim_prefix(type+"_").split("/")[0]) 173 | return target_chains[type][number][property.split("/")[1]] 174 | 175 | 176 | 177 | func _get_property_list(): 178 | var result:Array=[] 179 | _add_target_chain_property_to_list(TYPE_VECTOR2,"position",result) 180 | _add_target_chain_property_to_list(TYPE_FLOAT,"rotation",result) 181 | _add_target_chain_property_to_list(TYPE_VECTOR2,"scale",result) 182 | return result 183 | 184 | 185 | func _add_target_chain_property_to_list(property_value_type:int,property_name:String,result:Array): 186 | result.append({ 187 | &"name": "%s_count" % property_name, 188 | &"type": TYPE_INT, 189 | &"usage": PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_ARRAY, 190 | &"hint": PROPERTY_HINT_NONE, 191 | &"hint_string": "", 192 | &"class_name": "%s,%s_"% [property_name,property_name], 193 | }) 194 | for i in target_chains[property_name].size(): 195 | result.append({ 196 | &"name": "%s_%s/goal" % [property_name,i], 197 | &"type": property_value_type, 198 | }) 199 | result.append({ 200 | &"name": "%s_%s/duration" % [property_name,i], 201 | &"type": TYPE_FLOAT, 202 | }) 203 | result.append({ 204 | &"name": "%s_%s/tween" % [property_name,i], 205 | &"type": TYPE_INT, 206 | &"hint": PROPERTY_HINT_ENUM, 207 | &"hint_string":",".join(ClassDB.class_get_enum_constants("Tween","TransitionType")) 208 | }) 209 | return result 210 | #endregion 211 | -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedItem/FancyAnimatedItem/FancyAnimatedItem.gd.uid: -------------------------------------------------------------------------------- 1 | uid://gjs8jrwt2vyj 2 | -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedKeepContainer/AnimatedKeepContainer.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends AnimatedContainer 3 | class_name AnimatedKeepContainer 4 | ## not fully implemented yet. 5 | ## @experimental 6 | 7 | 8 | 9 | func _ready(): 10 | pass 11 | 12 | 13 | 14 | 15 | 16 | func _get_configuration_warnings(): 17 | return ["Experimental Container. Not fully implemented."] 18 | -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedKeepContainer/AnimatedKeepContainer.gd.uid: -------------------------------------------------------------------------------- 1 | uid://c4sugsnq67cai 2 | -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedRoundContainer/AnimatedRoundContainer.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | @icon("res://addons/FancyControls/Controls/AnimatedRoundContainer/AnimatedRoundContainer.png") 3 | extends AnimatedContainer 4 | class_name AnimatedRoundContainer 5 | 6 | 7 | @export_enum("Clockwise","CounterClockwise") var box_direction:int=0: 8 | set(v): 9 | box_direction=v 10 | _notification(NOTIFICATION_RESIZED) 11 | 12 | @export var do_rotation:bool=true 13 | @export var initial_rotation_degrees:float=0.0: 14 | set(v): 15 | initial_rotation_degrees=v 16 | _notification(NOTIFICATION_RESIZED) 17 | 18 | 19 | 20 | func _ready(): 21 | super._ready() 22 | if Engine.is_editor_hint():return 23 | initial_rotation_degrees=deg_to_rad(initial_rotation_degrees) 24 | 25 | 26 | 27 | func _update_spacings(animated:bool=true)->void: 28 | _update_start_positions() 29 | animated = animated and not Engine.is_editor_hint() 30 | if get_child_count()==0:return 31 | 32 | var nodes_to_space=get_children() 33 | var node_count=nodes_to_space.size() 34 | var available_space=size*0.5 35 | 36 | for id in node_count: 37 | var target_position=get_target_position_for_item(id) 38 | var target_rotation=lerp_angle(nodes_to_space[id].targeted_rotation,(id/float(node_count))*PI*2*(box_direction*2-1)+initial_rotation_degrees,1.0) 39 | 40 | if not (animate_spacing and animated): 41 | nodes_to_space[id].global_position=target_position 42 | if do_rotation:nodes_to_space[id].rotation=target_rotation 43 | if do_rotation:nodes_to_space[id].targeted_rotation=target_rotation 44 | nodes_to_space[id].targeted_position=target_position 45 | nodes_to_space[id].targeted_scale=Vector2.ONE 46 | #prevent an error from no tweened values 47 | 48 | 49 | func _editor_fit_contents()->void: 50 | var nodes_to_space=get_children() 51 | var node_count=nodes_to_space.size() 52 | var offset=size*0.5 53 | for id in node_count: 54 | var target_position=get_target_position_for_item(id)-nodes_to_space[id].size*0.5 55 | nodes_to_space[id].global_position=target_position 56 | nodes_to_space[id].scale=Vector2.ONE 57 | 58 | func get_target_position_for_item(id:int)->Vector2: 59 | var node_count=get_child_count() 60 | var available_space=(size.x if box_direction==1 else size.y) 61 | var spaced_position=Vector2(0,-1).rotated((id/float(node_count))*PI*2*(box_direction*2-1)+initial_rotation_degrees) 62 | var target_position=(spaced_position*(size*0.5-border_padding)+size*0.5)+global_position 63 | return target_position 64 | -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedRoundContainer/AnimatedRoundContainer.gd.uid: -------------------------------------------------------------------------------- 1 | uid://w1rwmh4hb4qn 2 | -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedRoundContainer/AnimatedRoundContainer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RogerRandomDev/FancyControls/0857c63136dafbd05c85d05faeb2e75fd8885a74/addons/FancyControls/Controls/AnimatedRoundContainer/AnimatedRoundContainer.png -------------------------------------------------------------------------------- /addons/FancyControls/Controls/AnimatedRoundContainer/AnimatedRoundContainer.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://bkmiynpwrmxkf" 6 | path="res://.godot/imported/AnimatedRoundContainer.png-343fad42d60174b0773df5f0de35eedb.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/FancyControls/Controls/AnimatedRoundContainer/AnimatedRoundContainer.png" 14 | dest_files=["res://.godot/imported/AnimatedRoundContainer.png-343fad42d60174b0773df5f0de35eedb.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /addons/FancyControls/Example/Example.FACSVis: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RogerRandomDev/FancyControls/0857c63136dafbd05c85d05faeb2e75fd8885a74/addons/FancyControls/Example/Example.FACSVis -------------------------------------------------------------------------------- /addons/FancyControls/Example/Example.FACSVis.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="FACS.Visual" 4 | type="Resource" 5 | uid="uid://bhnem44vn24a4" 6 | path="res://.godot/imported/Example.FACSVis-da3627dd90769ec1f3205f238f602902.res" 7 | 8 | [deps] 9 | 10 | source_file="res://addons/FancyControls/Example/Example.FACSVis" 11 | dest_files=["res://.godot/imported/Example.FACSVis-da3627dd90769ec1f3205f238f602902.res"] 12 | 13 | [params] 14 | 15 | -------------------------------------------------------------------------------- /addons/FancyControls/Example/ExampleGroup.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends RefCounted 3 | #WARNING 4 | #ANY CHANGES MADE TO FUNCTIONS BEING RE-COMPILED WILL BE OVERWRITTEN 5 | 6 | func Example(item_node:AnimatedItem,item_index:float=0,total_items:float=1,container_info={},_external_variables={}): 7 | 8 | var Div2 = item_index/total_items 9 | var Mul6 = Div2*-6.28 10 | var Rotate7 = Vector2(0, -32).rotated(Mul6) 11 | var Add8 = Rotate7+container_info.item_origins[item_index] 12 | var Sub3 = container_info.item_origins[item_index]-Rotate7 13 | var RandomFloat9 = randf_range(0.25,0.5) 14 | item_node.chain_action(0,Sub3,RandomFloat9,Tween.TRANS_SINE,false) #Position 15 | item_node.chain_action(0,Add8,1.0,Tween.TRANS_ELASTIC,false) #Position 16 | pass 17 | -------------------------------------------------------------------------------- /addons/FancyControls/Example/ExampleGroup.gd.uid: -------------------------------------------------------------------------------- 1 | uid://lb0tljy7gr5g 2 | -------------------------------------------------------------------------------- /addons/FancyControls/Example/test_hover.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | class_name AnimatedFuncs 3 | 4 | 5 | func item_hovered_example(item:AnimatedItem)->void: 6 | item.set_stacked_position(Vector2(0,-8),0.0625,Tween.TRANS_CIRC) 7 | item.set_stacked_scale(Vector2(1.25,1.25),0.125,Tween.TRANS_BACK) 8 | func item_unhovered_example(item:AnimatedItem)->void: 9 | item.set_stacked_position(Vector2(0,0),0.0625,Tween.TRANS_CIRC) 10 | item.set_stacked_scale(Vector2.ONE,0.0625,Tween.TRANS_BACK) 11 | -------------------------------------------------------------------------------- /addons/FancyControls/Example/test_hover.gd.uid: -------------------------------------------------------------------------------- 1 | uid://c6jyoea8on5o2 2 | -------------------------------------------------------------------------------- /addons/FancyControls/Example/testing.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | 4 | 5 | 6 | func _on_button_pressed(): 7 | if $VBoxContainer/AnimatedBoxContainer.get_child_count()<=0:return 8 | $VBoxContainer/AnimatedBoxContainer2.add_item($VBoxContainer/AnimatedBoxContainer.get_item(0),true) 9 | 10 | 11 | func _on_button_2_pressed(): 12 | if $VBoxContainer/AnimatedBoxContainer2.get_child_count()<=0:return 13 | $VBoxContainer/AnimatedBoxContainer.add_item($VBoxContainer/AnimatedBoxContainer2.get_item(0),true) 14 | 15 | 16 | func _on_button_3_pressed(): 17 | if $VBoxContainer/HBoxContainer/AnimatedRoundContainer2.get_child_count()<=0:return 18 | $VBoxContainer/HBoxContainer/AnimatedRoundContainer.add_item($VBoxContainer/HBoxContainer/AnimatedRoundContainer2.get_item(0),true) 19 | 20 | 21 | func _on_button_4_pressed(): 22 | if $VBoxContainer/HBoxContainer/AnimatedRoundContainer.get_child_count()<=0:return 23 | $VBoxContainer/HBoxContainer/AnimatedRoundContainer2.add_item($VBoxContainer/HBoxContainer/AnimatedRoundContainer.get_item(0),true) 24 | 25 | 26 | func _on_toggle_slidein_pressed(): 27 | $VBoxContainer/AnimatedGridSlideInContainer.active=!$VBoxContainer/AnimatedGridSlideInContainer.active 28 | 29 | 30 | func _on_toggle_fromcenter_round_pressed(): 31 | $VBoxContainer/HBoxContainer/AnimatedRoundContainer2.active=!$VBoxContainer/HBoxContainer/AnimatedRoundContainer2.active 32 | 33 | 34 | func _on_cycle_left_pressed(): 35 | $VBoxContainer/HBoxContainer/AnimatedRoundContainer.shift_items_forward() 36 | func _on_cycle_left_back_pressed(): 37 | $VBoxContainer/HBoxContainer/AnimatedRoundContainer.shift_items_back() 38 | 39 | 40 | 41 | 42 | 43 | func _on_cycle_right_pressed(): 44 | $VBoxContainer/HBoxContainer/AnimatedRoundContainer2.shift_items_forward() 45 | 46 | 47 | func _on_cycle_right_bacck_pressed(): 48 | $VBoxContainer/HBoxContainer/AnimatedRoundContainer2.shift_items_back() 49 | 50 | 51 | func _on_button_7_pressed(): 52 | $VBoxContainer/HBoxContainer/AnimatedRoundContainer._editor_fit_contents() 53 | $VBoxContainer/HBoxContainer/AnimatedRoundContainer.play_animation("Example") 54 | -------------------------------------------------------------------------------- /addons/FancyControls/Example/testing.gd.uid: -------------------------------------------------------------------------------- 1 | uid://bcy1m4vu6ttxt 2 | -------------------------------------------------------------------------------- /addons/FancyControls/Example/testing.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=8 format=3 uid="uid://dyd671fyvenq3"] 2 | 3 | [ext_resource type="Script" uid="uid://bcy1m4vu6ttxt" path="res://addons/FancyControls/Example/testing.gd" id="1_4dv0c"] 4 | [ext_resource type="Script" uid="uid://brvwggj2pxm6j" path="res://addons/FancyControls/Controls/AnimatedBoxContainer/AnimatedBoxContainer.gd" id="1_hssgr"] 5 | [ext_resource type="Script" uid="uid://c6jyoea8on5o2" path="res://addons/FancyControls/Example/test_hover.gd" id="3_4t6cu"] 6 | [ext_resource type="Script" uid="uid://w1rwmh4hb4qn" path="res://addons/FancyControls/Controls/AnimatedRoundContainer/AnimatedRoundContainer.gd" id="3_j83mo"] 7 | [ext_resource type="Script" uid="uid://lb0tljy7gr5g" path="res://addons/FancyControls/Example/ExampleGroup.gd" id="4_xuakl"] 8 | [ext_resource type="Script" uid="uid://meu2sn4owjwk" path="res://addons/FancyControls/Controls/AnimatedFromCenterRoundContainer/AnimatedFromCenterRoundContainer.gd" id="5_4vyu1"] 9 | [ext_resource type="Script" uid="uid://c1c16msvvybt6" path="res://addons/FancyControls/Controls/AnimatedGridSlideInContainer/AnimatedGridSlideInContainer.gd" id="5_lwohf"] 10 | 11 | [node name="Control" type="Control"] 12 | layout_mode = 3 13 | anchors_preset = 15 14 | anchor_right = 1.0 15 | anchor_bottom = 1.0 16 | grow_horizontal = 2 17 | grow_vertical = 2 18 | size_flags_horizontal = 3 19 | size_flags_vertical = 3 20 | script = ExtResource("1_4dv0c") 21 | 22 | [node name="VBoxContainer" type="VBoxContainer" parent="."] 23 | layout_mode = 1 24 | anchors_preset = 15 25 | anchor_right = 1.0 26 | anchor_bottom = 1.0 27 | grow_horizontal = 2 28 | grow_vertical = 2 29 | 30 | [node name="AnimatedBoxContainer" type="Control" parent="VBoxContainer"] 31 | custom_minimum_size = Vector2(40, 40) 32 | layout_mode = 2 33 | script = ExtResource("1_hssgr") 34 | box_direction = 1 35 | item_function_script = ExtResource("3_4t6cu") 36 | _hovered = &"" 37 | _unhovered = &"" 38 | _focused = &"" 39 | _unfocused = &"" 40 | _input = &"" 41 | 42 | [node name="Panel" type="Panel" parent="VBoxContainer/AnimatedBoxContainer"] 43 | layout_mode = 0 44 | offset_left = 48.0 45 | offset_right = 88.0 46 | offset_bottom = 40.0 47 | 48 | [node name="Panel2" type="Panel" parent="VBoxContainer/AnimatedBoxContainer"] 49 | layout_mode = 0 50 | offset_left = 144.0 51 | offset_right = 184.0 52 | offset_bottom = 40.0 53 | 54 | [node name="Panel3" type="Panel" parent="VBoxContainer/AnimatedBoxContainer"] 55 | layout_mode = 0 56 | offset_left = 240.0 57 | offset_right = 280.0 58 | offset_bottom = 40.0 59 | 60 | [node name="Panel4" type="Panel" parent="VBoxContainer/AnimatedBoxContainer"] 61 | layout_mode = 0 62 | offset_left = 336.0 63 | offset_right = 376.0 64 | offset_bottom = 40.0 65 | 66 | [node name="Panel5" type="Panel" parent="VBoxContainer/AnimatedBoxContainer"] 67 | layout_mode = 0 68 | offset_left = 432.0 69 | offset_right = 472.0 70 | offset_bottom = 40.0 71 | 72 | [node name="Panel6" type="Panel" parent="VBoxContainer/AnimatedBoxContainer"] 73 | layout_mode = 0 74 | offset_left = 528.0 75 | offset_right = 568.0 76 | offset_bottom = 40.0 77 | 78 | [node name="Panel7" type="Panel" parent="VBoxContainer/AnimatedBoxContainer"] 79 | layout_mode = 0 80 | offset_left = 624.0 81 | offset_right = 664.0 82 | offset_bottom = 40.0 83 | 84 | [node name="Panel8" type="Panel" parent="VBoxContainer/AnimatedBoxContainer"] 85 | layout_mode = 0 86 | offset_left = 720.0 87 | offset_right = 760.0 88 | offset_bottom = 40.0 89 | 90 | [node name="Panel9" type="Panel" parent="VBoxContainer/AnimatedBoxContainer"] 91 | layout_mode = 0 92 | offset_left = 816.0 93 | offset_right = 856.0 94 | offset_bottom = 40.0 95 | 96 | [node name="Panel10" type="Panel" parent="VBoxContainer/AnimatedBoxContainer"] 97 | layout_mode = 0 98 | offset_left = 912.0 99 | offset_right = 952.0 100 | offset_bottom = 40.0 101 | 102 | [node name="Panel11" type="Panel" parent="VBoxContainer/AnimatedBoxContainer"] 103 | layout_mode = 0 104 | offset_left = 1008.0 105 | offset_right = 1048.0 106 | offset_bottom = 40.0 107 | 108 | [node name="Panel12" type="Panel" parent="VBoxContainer/AnimatedBoxContainer"] 109 | layout_mode = 0 110 | offset_left = 1104.0 111 | offset_right = 1144.0 112 | offset_bottom = 40.0 113 | 114 | [node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] 115 | layout_mode = 2 116 | size_flags_vertical = 3 117 | theme_override_constants/separation = 256 118 | 119 | [node name="AnimatedRoundContainer" type="Control" parent="VBoxContainer/HBoxContainer"] 120 | custom_minimum_size = Vector2(0, 214) 121 | layout_mode = 2 122 | size_flags_horizontal = 3 123 | size_flags_vertical = 4 124 | mouse_filter = 1 125 | script = ExtResource("3_j83mo") 126 | do_rotation = false 127 | border_padding = Vector2(24, 24) 128 | animation_group = ExtResource("4_xuakl") 129 | item_function_script = ExtResource("3_4t6cu") 130 | _hovered = &"item_hovered_example" 131 | _unhovered = &"item_unhovered_example" 132 | _focused = &"" 133 | _unfocused = &"" 134 | _input = &"" 135 | 136 | [node name="Panel" type="Panel" parent="VBoxContainer/HBoxContainer/AnimatedRoundContainer"] 137 | layout_mode = 0 138 | offset_left = 86.5 139 | offset_top = 4.0 140 | offset_right = 126.5 141 | offset_bottom = 44.0 142 | 143 | [node name="Panel2" type="Panel" parent="VBoxContainer/HBoxContainer/AnimatedRoundContainer"] 144 | layout_mode = 0 145 | offset_left = 28.1637 146 | offset_top = 28.3101 147 | offset_right = 68.1637 148 | offset_bottom = 68.3101 149 | 150 | [node name="Panel3" type="Panel" parent="VBoxContainer/HBoxContainer/AnimatedRoundContainer"] 151 | layout_mode = 0 152 | offset_left = 4.0 153 | offset_top = 87.0 154 | offset_right = 44.0 155 | offset_bottom = 127.0 156 | 157 | [node name="Panel4" type="Panel" parent="VBoxContainer/HBoxContainer/AnimatedRoundContainer"] 158 | layout_mode = 0 159 | offset_left = 28.1637 160 | offset_top = 145.69 161 | offset_right = 68.1637 162 | offset_bottom = 185.69 163 | 164 | [node name="Panel5" type="Panel" parent="VBoxContainer/HBoxContainer/AnimatedRoundContainer"] 165 | layout_mode = 0 166 | offset_left = 86.5 167 | offset_top = 170.0 168 | offset_right = 126.5 169 | offset_bottom = 210.0 170 | 171 | [node name="Panel6" type="Panel" parent="VBoxContainer/HBoxContainer/AnimatedRoundContainer"] 172 | layout_mode = 0 173 | offset_left = 144.836 174 | offset_top = 145.69 175 | offset_right = 184.836 176 | offset_bottom = 185.69 177 | 178 | [node name="Panel7" type="Panel" parent="VBoxContainer/HBoxContainer/AnimatedRoundContainer"] 179 | layout_mode = 0 180 | offset_left = 169.0 181 | offset_top = 87.0 182 | offset_right = 209.0 183 | offset_bottom = 127.0 184 | 185 | [node name="Panel8" type="Panel" parent="VBoxContainer/HBoxContainer/AnimatedRoundContainer"] 186 | layout_mode = 0 187 | offset_left = 144.836 188 | offset_top = 28.3101 189 | offset_right = 184.836 190 | offset_bottom = 68.3102 191 | 192 | [node name="Buttons" type="Control" parent="VBoxContainer/HBoxContainer"] 193 | custom_minimum_size = Vector2(0, 213) 194 | layout_mode = 2 195 | size_flags_horizontal = 3 196 | size_flags_vertical = 4 197 | script = ExtResource("3_j83mo") 198 | do_rotation = false 199 | _hovered = &"" 200 | _unhovered = &"" 201 | _focused = &"" 202 | _unfocused = &"" 203 | _input = &"" 204 | 205 | [node name="Button2" type="Button" parent="VBoxContainer/HBoxContainer/Buttons"] 206 | layout_mode = 2 207 | offset_left = 57.0 208 | offset_top = -15.5 209 | offset_right = 156.0 210 | offset_bottom = 15.5 211 | text = "Swap Up" 212 | 213 | [node name="Button3" type="Button" parent="VBoxContainer/HBoxContainer/Buttons"] 214 | layout_mode = 2 215 | offset_left = -49.5 216 | offset_top = 91.0 217 | offset_right = 49.5 218 | offset_bottom = 122.0 219 | text = "Swap Left" 220 | 221 | [node name="Button" type="Button" parent="VBoxContainer/HBoxContainer/Buttons"] 222 | layout_mode = 2 223 | offset_left = 57.0 224 | offset_top = 197.5 225 | offset_right = 156.0 226 | offset_bottom = 228.5 227 | text = "Swap Down" 228 | 229 | [node name="Button4" type="Button" parent="VBoxContainer/HBoxContainer/Buttons"] 230 | layout_mode = 2 231 | offset_left = 163.5 232 | offset_top = 91.0 233 | offset_right = 262.5 234 | offset_bottom = 122.0 235 | text = "Swap Right" 236 | 237 | [node name="AnimatedRoundContainer2" type="Control" parent="VBoxContainer/HBoxContainer"] 238 | custom_minimum_size = Vector2(0, 214) 239 | layout_mode = 2 240 | size_flags_horizontal = 3 241 | size_flags_vertical = 4 242 | mouse_filter = 1 243 | script = ExtResource("5_4vyu1") 244 | active = true 245 | box_direction = 1 246 | border_padding = Vector2(24, 24) 247 | _hovered = &"" 248 | _unhovered = &"" 249 | _focused = &"" 250 | _unfocused = &"" 251 | _input = &"" 252 | 253 | [node name="Panel" type="Panel" parent="VBoxContainer/HBoxContainer/AnimatedRoundContainer2"] 254 | layout_mode = 0 255 | offset_left = 87.0 256 | offset_top = 4.0 257 | offset_right = 127.0 258 | offset_bottom = 44.0 259 | 260 | [node name="Panel2" type="Panel" parent="VBoxContainer/HBoxContainer/AnimatedRoundContainer2"] 261 | layout_mode = 0 262 | offset_left = 145.69 263 | offset_top = 28.3101 264 | offset_right = 185.69 265 | offset_bottom = 68.3101 266 | 267 | [node name="Panel3" type="Panel" parent="VBoxContainer/HBoxContainer/AnimatedRoundContainer2"] 268 | layout_mode = 0 269 | offset_left = 170.0 270 | offset_top = 87.0 271 | offset_right = 210.0 272 | offset_bottom = 127.0 273 | 274 | [node name="Panel4" type="Panel" parent="VBoxContainer/HBoxContainer/AnimatedRoundContainer2"] 275 | layout_mode = 0 276 | offset_left = 145.69 277 | offset_top = 145.69 278 | offset_right = 185.69 279 | offset_bottom = 185.69 280 | 281 | [node name="Panel5" type="Panel" parent="VBoxContainer/HBoxContainer/AnimatedRoundContainer2"] 282 | layout_mode = 0 283 | offset_left = 87.0 284 | offset_top = 170.0 285 | offset_right = 127.0 286 | offset_bottom = 210.0 287 | 288 | [node name="Panel6" type="Panel" parent="VBoxContainer/HBoxContainer/AnimatedRoundContainer2"] 289 | layout_mode = 0 290 | offset_left = 28.3101 291 | offset_top = 145.69 292 | offset_right = 68.3102 293 | offset_bottom = 185.69 294 | 295 | [node name="Panel7" type="Panel" parent="VBoxContainer/HBoxContainer/AnimatedRoundContainer2"] 296 | layout_mode = 0 297 | offset_left = 4.0 298 | offset_top = 87.0 299 | offset_right = 44.0 300 | offset_bottom = 127.0 301 | 302 | [node name="Panel8" type="Panel" parent="VBoxContainer/HBoxContainer/AnimatedRoundContainer2"] 303 | layout_mode = 0 304 | offset_left = 28.3102 305 | offset_top = 28.3101 306 | offset_right = 68.3101 307 | offset_bottom = 68.3102 308 | 309 | [node name="AnimatedBoxContainer2" type="Control" parent="VBoxContainer"] 310 | custom_minimum_size = Vector2(0, 40) 311 | layout_mode = 2 312 | script = ExtResource("1_hssgr") 313 | box_direction = 1 314 | _hovered = &"" 315 | _unhovered = &"" 316 | _focused = &"" 317 | _unfocused = &"" 318 | _input = &"" 319 | 320 | [node name="AnimatedGridSlideInContainer" type="Control" parent="VBoxContainer"] 321 | custom_minimum_size = Vector2(0, 256) 322 | layout_mode = 2 323 | size_flags_vertical = 3 324 | mouse_filter = 1 325 | script = ExtResource("5_lwohf") 326 | slide_from_direction = Vector2(0, 1) 327 | expand_direction = 1 328 | item_spacing = Vector2(42, 42) 329 | item_function_script = ExtResource("3_4t6cu") 330 | _hovered = &"item_hovered_example" 331 | _unhovered = &"item_unhovered_example" 332 | _focused = &"" 333 | _unfocused = &"" 334 | _input = &"" 335 | 336 | [node name="Panel" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 337 | layout_mode = 0 338 | offset_top = 278.0 339 | offset_right = 40.0 340 | offset_bottom = 318.0 341 | 342 | [node name="Panel117" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 343 | layout_mode = 0 344 | offset_top = 324.333 345 | offset_right = 40.0 346 | offset_bottom = 364.333 347 | 348 | [node name="Panel118" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 349 | layout_mode = 0 350 | offset_top = 370.667 351 | offset_right = 40.0 352 | offset_bottom = 410.667 353 | 354 | [node name="Panel114" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 355 | layout_mode = 0 356 | offset_top = 417.0 357 | offset_right = 39.9999 358 | offset_bottom = 457.0 359 | 360 | [node name="Panel116" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 361 | layout_mode = 0 362 | offset_top = 463.333 363 | offset_right = 40.0 364 | offset_bottom = 503.333 365 | 366 | [node name="Panel115" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 367 | layout_mode = 0 368 | offset_top = 509.667 369 | offset_right = 39.9999 370 | offset_bottom = 549.667 371 | 372 | [node name="Panel2" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 373 | layout_mode = 0 374 | offset_left = 42.0 375 | offset_top = 278.0 376 | offset_right = 82.0001 377 | offset_bottom = 318.0 378 | 379 | [node name="Panel27" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 380 | layout_mode = 0 381 | offset_left = 42.0 382 | offset_top = 324.333 383 | offset_right = 82.0001 384 | offset_bottom = 364.333 385 | 386 | [node name="Panel3" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 387 | layout_mode = 0 388 | offset_left = 42.0 389 | offset_top = 370.667 390 | offset_right = 81.9998 391 | offset_bottom = 410.667 392 | 393 | [node name="Panel5" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 394 | layout_mode = 0 395 | offset_left = 42.0 396 | offset_top = 417.0 397 | offset_right = 81.9996 398 | offset_bottom = 457.0 399 | 400 | [node name="Panel113" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 401 | layout_mode = 0 402 | offset_left = 42.0 403 | offset_top = 463.333 404 | offset_right = 81.9998 405 | offset_bottom = 503.333 406 | 407 | [node name="Panel6" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 408 | layout_mode = 0 409 | offset_left = 42.0 410 | offset_top = 509.667 411 | offset_right = 81.9998 412 | offset_bottom = 549.667 413 | 414 | [node name="Panel7" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 415 | layout_mode = 0 416 | offset_left = 84.0 417 | offset_top = 278.0 418 | offset_right = 124.0 419 | offset_bottom = 318.0 420 | 421 | [node name="Panel4" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 422 | layout_mode = 0 423 | offset_left = 84.0 424 | offset_top = 324.333 425 | offset_right = 124.0 426 | offset_bottom = 364.333 427 | 428 | [node name="Panel8" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 429 | layout_mode = 0 430 | offset_left = 84.0 431 | offset_top = 370.667 432 | offset_right = 124.0 433 | offset_bottom = 410.667 434 | 435 | [node name="Panel9" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 436 | layout_mode = 0 437 | offset_left = 84.0 438 | offset_top = 417.0 439 | offset_right = 124.0 440 | offset_bottom = 457.0 441 | 442 | [node name="Panel10" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 443 | layout_mode = 0 444 | offset_left = 84.0 445 | offset_top = 463.333 446 | offset_right = 124.0 447 | offset_bottom = 503.333 448 | 449 | [node name="Panel11" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 450 | layout_mode = 0 451 | offset_left = 84.0 452 | offset_top = 509.667 453 | offset_right = 124.0 454 | offset_bottom = 549.667 455 | 456 | [node name="Panel12" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 457 | layout_mode = 0 458 | offset_left = 126.0 459 | offset_top = 278.0 460 | offset_right = 166.0 461 | offset_bottom = 318.0 462 | 463 | [node name="Panel13" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 464 | layout_mode = 0 465 | offset_left = 126.0 466 | offset_top = 324.333 467 | offset_right = 166.0 468 | offset_bottom = 364.333 469 | 470 | [node name="Panel14" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 471 | layout_mode = 0 472 | offset_left = 126.0 473 | offset_top = 370.667 474 | offset_right = 166.0 475 | offset_bottom = 410.667 476 | 477 | [node name="Panel15" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 478 | layout_mode = 0 479 | offset_left = 126.0 480 | offset_top = 417.0 481 | offset_right = 166.0 482 | offset_bottom = 457.0 483 | 484 | [node name="Panel16" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 485 | layout_mode = 0 486 | offset_left = 126.0 487 | offset_top = 463.333 488 | offset_right = 166.0 489 | offset_bottom = 503.333 490 | 491 | [node name="Panel17" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 492 | layout_mode = 0 493 | offset_left = 126.0 494 | offset_top = 509.667 495 | offset_right = 166.0 496 | offset_bottom = 549.667 497 | 498 | [node name="Panel18" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 499 | layout_mode = 0 500 | offset_left = 168.0 501 | offset_top = 278.0 502 | offset_right = 207.999 503 | offset_bottom = 318.0 504 | 505 | [node name="Panel19" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 506 | layout_mode = 0 507 | offset_left = 168.0 508 | offset_top = 324.333 509 | offset_right = 208.0 510 | offset_bottom = 364.333 511 | 512 | [node name="Panel20" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 513 | layout_mode = 0 514 | offset_left = 168.0 515 | offset_top = 370.667 516 | offset_right = 208.0 517 | offset_bottom = 410.667 518 | 519 | [node name="Panel21" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 520 | layout_mode = 0 521 | offset_left = 168.0 522 | offset_top = 417.0 523 | offset_right = 208.0 524 | offset_bottom = 457.0 525 | 526 | [node name="Panel22" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 527 | layout_mode = 0 528 | offset_left = 168.0 529 | offset_top = 463.333 530 | offset_right = 208.0 531 | offset_bottom = 503.333 532 | 533 | [node name="Panel23" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 534 | layout_mode = 0 535 | offset_left = 168.0 536 | offset_top = 509.667 537 | offset_right = 208.0 538 | offset_bottom = 549.667 539 | 540 | [node name="Panel24" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 541 | layout_mode = 0 542 | offset_left = 210.0 543 | offset_top = 278.0 544 | offset_right = 249.999 545 | offset_bottom = 318.0 546 | 547 | [node name="Panel25" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 548 | layout_mode = 0 549 | offset_left = 210.0 550 | offset_top = 324.333 551 | offset_right = 250.0 552 | offset_bottom = 364.333 553 | 554 | [node name="Panel35" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 555 | layout_mode = 0 556 | offset_left = 210.0 557 | offset_top = 370.667 558 | offset_right = 250.0 559 | offset_bottom = 410.667 560 | 561 | [node name="Panel36" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 562 | layout_mode = 0 563 | offset_left = 210.0 564 | offset_top = 417.0 565 | offset_right = 250.0 566 | offset_bottom = 457.0 567 | 568 | [node name="Panel26" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 569 | layout_mode = 0 570 | offset_left = 210.0 571 | offset_top = 463.333 572 | offset_right = 250.0 573 | offset_bottom = 503.333 574 | 575 | [node name="Panel28" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 576 | layout_mode = 0 577 | offset_left = 210.0 578 | offset_top = 509.667 579 | offset_right = 250.0 580 | offset_bottom = 549.667 581 | 582 | [node name="Panel29" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 583 | layout_mode = 0 584 | offset_left = 252.0 585 | offset_top = 278.0 586 | offset_right = 292.0 587 | offset_bottom = 318.0 588 | 589 | [node name="Panel30" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 590 | layout_mode = 0 591 | offset_left = 252.0 592 | offset_top = 324.333 593 | offset_right = 292.0 594 | offset_bottom = 364.333 595 | 596 | [node name="Panel31" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 597 | layout_mode = 0 598 | offset_left = 252.0 599 | offset_top = 370.667 600 | offset_right = 292.0 601 | offset_bottom = 410.667 602 | 603 | [node name="Panel32" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 604 | layout_mode = 0 605 | offset_left = 252.0 606 | offset_top = 417.0 607 | offset_right = 292.0 608 | offset_bottom = 457.0 609 | 610 | [node name="Panel33" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 611 | layout_mode = 0 612 | offset_left = 252.0 613 | offset_top = 463.333 614 | offset_right = 292.0 615 | offset_bottom = 503.333 616 | 617 | [node name="Panel34" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 618 | layout_mode = 0 619 | offset_left = 252.0 620 | offset_top = 509.667 621 | offset_right = 292.0 622 | offset_bottom = 549.667 623 | 624 | [node name="Panel37" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 625 | layout_mode = 0 626 | offset_left = 294.0 627 | offset_top = 278.0 628 | offset_right = 334.0 629 | offset_bottom = 318.0 630 | 631 | [node name="Panel119" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 632 | layout_mode = 0 633 | offset_left = 294.0 634 | offset_top = 324.333 635 | offset_right = 334.0 636 | offset_bottom = 364.333 637 | 638 | [node name="Panel120" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 639 | layout_mode = 0 640 | offset_left = 294.0 641 | offset_top = 370.667 642 | offset_right = 334.0 643 | offset_bottom = 410.667 644 | 645 | [node name="Panel121" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 646 | layout_mode = 0 647 | offset_left = 294.0 648 | offset_top = 417.0 649 | offset_right = 334.0 650 | offset_bottom = 457.0 651 | 652 | [node name="Panel122" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 653 | layout_mode = 0 654 | offset_left = 294.0 655 | offset_top = 463.333 656 | offset_right = 334.0 657 | offset_bottom = 503.333 658 | 659 | [node name="Panel123" type="Panel" parent="VBoxContainer/AnimatedGridSlideInContainer"] 660 | layout_mode = 0 661 | offset_left = 294.0 662 | offset_top = 509.667 663 | offset_right = 334.0 664 | offset_bottom = 549.667 665 | 666 | [node name="Label" type="Label" parent="."] 667 | layout_mode = 0 668 | offset_left = 33.0 669 | offset_top = 142.0 670 | offset_right = 184.0 671 | offset_bottom = 191.0 672 | text = "Has hover/unhover 673 | linked to a function, 674 | has animation group set 675 | " 676 | 677 | [node name="Label2" type="Label" parent="."] 678 | layout_mode = 0 679 | offset_left = 40.0 680 | offset_top = 33.0 681 | offset_right = 191.0 682 | offset_bottom = 82.0 683 | text = "Has hover/unhover 684 | linked to a function" 685 | 686 | [node name="Label3" type="Label" parent="."] 687 | layout_mode = 0 688 | offset_left = 28.0 689 | offset_top = 315.0 690 | offset_right = 179.0 691 | offset_bottom = 364.0 692 | text = "Has hover/unhover 693 | linked to a function" 694 | 695 | [node name="Label5" type="Label" parent="."] 696 | layout_mode = 0 697 | offset_left = 406.0 698 | offset_top = 210.0 699 | offset_right = 757.0 700 | offset_bottom = 259.0 701 | text = "This also uses one of the containers 702 | they can use any control node not just panels" 703 | horizontal_alignment = 1 704 | 705 | [node name="Label4" type="Label" parent="."] 706 | layout_mode = 0 707 | offset_left = 969.0 708 | offset_top = 150.0 709 | offset_right = 1120.0 710 | offset_bottom = 199.0 711 | text = "does not have any 712 | signals linked" 713 | horizontal_alignment = 1 714 | 715 | [node name="Button" type="Button" parent="."] 716 | layout_mode = 0 717 | offset_left = 391.0 718 | offset_top = 503.0 719 | offset_right = 540.0 720 | offset_bottom = 534.0 721 | text = "Toggle SlideIn grid" 722 | 723 | [node name="Button2" type="Button" parent="."] 724 | layout_mode = 0 725 | offset_left = 766.0 726 | offset_top = 161.0 727 | offset_right = 917.0 728 | offset_bottom = 215.0 729 | text = "Toggle fromcenter 730 | round container" 731 | 732 | [node name="Button3" type="Button" parent="."] 733 | layout_mode = 0 734 | offset_left = 809.0 735 | offset_top = 65.0 736 | offset_right = 938.0 737 | offset_bottom = 96.0 738 | text = "Cycle Container" 739 | 740 | [node name="Button6" type="Button" parent="."] 741 | layout_mode = 0 742 | offset_left = 808.0 743 | offset_top = 102.0 744 | offset_right = 937.0 745 | offset_bottom = 156.0 746 | text = "Cycle Container 747 | Back" 748 | 749 | [node name="Button4" type="Button" parent="."] 750 | layout_mode = 0 751 | offset_left = 222.0 752 | offset_top = 73.0 753 | offset_right = 351.0 754 | offset_bottom = 104.0 755 | text = "Cycle Container" 756 | 757 | [node name="Button5" type="Button" parent="."] 758 | layout_mode = 0 759 | offset_left = 222.0 760 | offset_top = 112.0 761 | offset_right = 351.0 762 | offset_bottom = 166.0 763 | text = "Cycle Container 764 | Back" 765 | 766 | [node name="Button7" type="Button" parent="."] 767 | layout_mode = 0 768 | offset_left = 233.0 769 | offset_top = 175.0 770 | offset_right = 362.0 771 | offset_bottom = 229.0 772 | text = "Test animation" 773 | 774 | [connection signal="pressed" from="VBoxContainer/HBoxContainer/Buttons/Button2" to="." method="_on_button_2_pressed"] 775 | [connection signal="pressed" from="VBoxContainer/HBoxContainer/Buttons/Button3" to="." method="_on_button_3_pressed"] 776 | [connection signal="pressed" from="VBoxContainer/HBoxContainer/Buttons/Button" to="." method="_on_button_pressed"] 777 | [connection signal="pressed" from="VBoxContainer/HBoxContainer/Buttons/Button4" to="." method="_on_button_4_pressed"] 778 | [connection signal="pressed" from="Button" to="." method="_on_toggle_slidein_pressed"] 779 | [connection signal="pressed" from="Button2" to="." method="_on_toggle_fromcenter_round_pressed"] 780 | [connection signal="pressed" from="Button3" to="." method="_on_cycle_right_pressed"] 781 | [connection signal="pressed" from="Button6" to="." method="_on_cycle_right_bacck_pressed"] 782 | [connection signal="pressed" from="Button4" to="." method="_on_cycle_left_pressed"] 783 | [connection signal="pressed" from="Button5" to="." method="_on_cycle_left_back_pressed"] 784 | [connection signal="pressed" from="Button7" to="." method="_on_button_7_pressed"] 785 | -------------------------------------------------------------------------------- /addons/FancyControls/FACSManagerResource.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends Resource 3 | class_name FACSManagerResource 4 | 5 | var Groups:Dictionary={} 6 | @export var group_data:Dictionary={} 7 | 8 | func _init(): 9 | resource_name=&"FACSManagerStored" 10 | 11 | func load_from_data(): 12 | for group in group_data: 13 | Groups[group]=[] 14 | group_data[group].map(func(v): 15 | if len(v)>2: 16 | Groups[group].push_back(FACSGroupBinding.new(v[0],v[1],v[2])) 17 | else: 18 | Groups[group].push_back(FACSGroupBinding.new(v[0],v[1])) 19 | ) 20 | 21 | 22 | ##will return false only if the group can't be created with a given name 23 | func create_group(group_name:String)->bool: 24 | #regex magic is fun when it comes in handy. just prevents special characters mostly. 25 | if RegEx.create_from_string("\"(?:\\\\.|[^\"])*\"").search(group_name)!=null:return false 26 | if group_name.contains(" "):return false 27 | if Groups.has(group_name):return false 28 | var g=Groups.duplicate() 29 | g.merge({group_name:[]}) 30 | Groups=g 31 | resave.call_deferred() 32 | return true 33 | 34 | func remove_group(group_name:String): 35 | if not Groups.has(group_name):return 36 | Groups.erase(group_name) 37 | 38 | resave.call_deferred() 39 | 40 | 41 | 42 | 43 | 44 | func change_group_name(old_name:String,new_name:String)->bool: 45 | 46 | if !Groups.has(old_name):return false 47 | if RegEx.create_from_string("[^A-Za-z0-9_]").search(new_name)!=null:return false 48 | if new_name.contains(" "):return false 49 | if Groups.has(new_name):return false 50 | var new_group={new_name:Groups[old_name]} 51 | var g=Groups.duplicate() 52 | 53 | g.merge(new_group) 54 | g.erase(old_name) 55 | Groups=g 56 | resave.call_deferred() 57 | return true 58 | 59 | func change_group_binding_name(group_name:String,on_resource:FACSGroupBinding,new_name:String)->bool: 60 | 61 | if !Groups.has(group_name):return false 62 | if RegEx.create_from_string("[^A-Za-z0-9_]").search(new_name)!=null:return false 63 | if new_name.contains(" "):return false 64 | if Groups[group_name].any(func(v):return v.binding_name==new_name):return false 65 | var option=Groups[group_name].filter(func(v):return v.binding_name==on_resource.binding_name and v.binding_link_path==on_resource.binding_link_path) 66 | 67 | if len(option)==0:return false 68 | option[0].binding_name=new_name 69 | 70 | 71 | 72 | resave.call_deferred() 73 | 74 | return true 75 | 76 | 77 | func change_group_binding_script_method(group_name:String,on_resource:FACSGroupBinding,new_method:String)->bool: 78 | if !Groups.has(group_name):return false 79 | var option=Groups[group_name].filter(func(v):return v.binding_name==on_resource.binding_name and v.binding_link_path==on_resource.binding_link_path) 80 | 81 | if len(option)==0:return false 82 | option[0].binding_special_data=new_method 83 | 84 | 85 | 86 | resave.call_deferred() 87 | 88 | return true 89 | 90 | ##returns a [PackedStringArray] of the names of all groups 91 | func get_group_list()->Array: 92 | return Groups.keys() 93 | 94 | ##returns the content of the given group_name, defaults null if group does not exist 95 | func get_chains_in_group(group_name:String): 96 | return Groups.get(group_name) 97 | 98 | 99 | ##returns the list of groups containing any invalid/non-existent function links 100 | func get_invalid_groups()->PackedStringArray: 101 | var invalidGroups:PackedStringArray=PackedStringArray() 102 | for group in Groups.keys(): 103 | pass 104 | return invalidGroups 105 | 106 | ##returns an array of booleans listing what are/are not valid bindings to a group 107 | func get_invalid_bindings_in_group(group_name:String)->Array[bool]: 108 | if !Groups.has(group_name):return [] 109 | var arr:Array[bool]=[] 110 | Groups[group_name].map(func(v:FACSGroupBinding):arr.push_back(v.is_binding_valid())) 111 | 112 | return arr 113 | 114 | ##checks the given bind_name and bind_path can be added properly to the given group_name 115 | func check_facs_group_can_add(group_name:String,bind_name:String,bind_path:String)->bool: 116 | if !Groups.has(group_name):return false 117 | return not Groups[group_name].any(func(v):return v.binding_name==bind_name) 118 | 119 | ## creates a binding for the given path with the given name if it can 120 | func bind_facs_to_group(group_name:String,bind_name:String,bind_path:String)->void: 121 | if !Groups.has(group_name):return 122 | var bind=FACSGroupBinding.new(bind_name,bind_path) 123 | Groups[group_name].push_back(bind) 124 | resave.call_deferred() 125 | 126 | func rebind_path_on(group_name:String,on_resource,new_path:String)->void: 127 | if !Groups.has(group_name):return 128 | var option=Groups[group_name].filter(func(v):return v.binding_name==on_resource.binding_name and v.binding_link_path==on_resource.binding_link_path) 129 | if len(option)==0:return 130 | option[0].binding_link_path=new_path 131 | 132 | 133 | func remove_chain_from_group(group_name:String,chain_name:String)->void: 134 | if !Groups.has(group_name):return 135 | var option=Groups[group_name].filter(func(v):return v.binding_name==chain_name) 136 | if len(option)==0:return 137 | Groups[group_name].erase(option[0]) 138 | resave.call_deferred() 139 | 140 | func resave(): 141 | group_data={} 142 | for group in Groups: 143 | group_data[group]=[] 144 | for res in Groups[group]: 145 | group_data[group].push_back(res.get_arr_data()) 146 | 147 | ResourceSaver.save(self,"res://FACS/FACSManager.res") 148 | -------------------------------------------------------------------------------- /addons/FancyControls/FACSManagerResource.gd.uid: -------------------------------------------------------------------------------- 1 | uid://d8hlw4c4hhd1 2 | -------------------------------------------------------------------------------- /addons/FancyControls/FacsBinding.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends Resource 3 | ## used internally to manage the bindings data 4 | ## i could have just used a dictionary and more functions 5 | ## but this is cleaner to manage and puts more into separating purpose 6 | ## and allows me to focus on keeping it just more visually readable 7 | class_name FACSGroupBinding 8 | @export var binding_name:String 9 | @export var binding_special_data:String 10 | @export var binding_link_path:String 11 | @export var binding_valid:bool=true 12 | 13 | func _init(name:String,path:String,special:String=""): 14 | binding_name=name 15 | binding_special_data=special 16 | binding_link_path=path 17 | binding_valid=true 18 | 19 | func is_binding_valid()->bool: 20 | binding_valid=FileAccess.file_exists(binding_link_path) 21 | return binding_valid 22 | 23 | func insert_data_in_treeitem(item:TreeItem)->void: 24 | item.set_meta(&"linked_resource",self) 25 | 26 | item.set_text(0,binding_name) 27 | #this bit is for building the range select to choose the method for usage 28 | if binding_link_path.ends_with(".gd"): 29 | #why do they not document that you can do this? 30 | item.set_cell_mode(1,TreeItem.CELL_MODE_RANGE) 31 | var end_of_function_regex=RegEx.create_from_string("\\nfunc [0-z]+") 32 | var loading_script_contents=FileAccess.get_file_as_string(binding_link_path) 33 | var outputs=end_of_function_regex.search_all(loading_script_contents) 34 | item.set_text(1, 35 | ",".join(Array(outputs).map(func(v):return v.strings[0].trim_prefix("\nfunc "))) 36 | ) 37 | item.set_range(1,item.get_text(1).split(",").find(binding_special_data)) 38 | item.set_editable(1,true) 39 | 40 | 41 | item.set_text(2,binding_link_path) 42 | item.set_custom_color(2,Color.RED if !binding_valid else Color.WHITE) 43 | item.set_tooltip_text(2,"Invalid Path" if !binding_valid else "") 44 | 45 | item.set_text(3,"!" if !binding_valid else "") 46 | item.set_custom_color(3,Color.RED if !binding_valid else Color.WHITE) 47 | item.set_tooltip_text(3,"Invalid Path" if !binding_valid else "") 48 | item.set_text_alignment(3,HORIZONTAL_ALIGNMENT_CENTER) 49 | 50 | func get_arr_data()->Array: 51 | 52 | return [binding_name,binding_link_path,binding_special_data] 53 | 54 | -------------------------------------------------------------------------------- /addons/FancyControls/FacsBinding.gd.uid: -------------------------------------------------------------------------------- 1 | uid://dg447trl5ifqb 2 | -------------------------------------------------------------------------------- /addons/FancyControls/FacsLOGO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RogerRandomDev/FancyControls/0857c63136dafbd05c85d05faeb2e75fd8885a74/addons/FancyControls/FacsLOGO.png -------------------------------------------------------------------------------- /addons/FancyControls/FacsLOGO.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://wpybb601urwv" 6 | path="res://.godot/imported/FacsLOGO.png-e31bb991c789872ca1801dcb4d1b1fdb.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/FancyControls/FacsLOGO.png" 14 | dest_files=["res://.godot/imported/FacsLOGO.png-e31bb991c789872ca1801dcb4d1b1fdb.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /addons/FancyControls/FancyControls.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends EditorPlugin 3 | 4 | 5 | 6 | const MainPanel = preload("res://addons/FancyControls/GUI/scene/control.tscn") 7 | 8 | var main_panel_instance 9 | var import_plugin_animation 10 | var import_plugin_group 11 | 12 | func _enter_tree(): 13 | initialize_resources() 14 | 15 | import_plugin_animation= load("res://addons/FancyControls/Importers/FACSVisImporter.gd").new() 16 | import_plugin_group= load("res://addons/FancyControls/Importers/FacsVisGroupImporter.gd").new() 17 | add_import_plugin(import_plugin_animation) 18 | add_import_plugin(import_plugin_group) 19 | 20 | 21 | main_panel_instance = MainPanel.instantiate() 22 | 23 | # Add the main panel to the editor's main viewport. 24 | EditorInterface.get_editor_main_screen().add_child(main_panel_instance) 25 | # Hide the main panel. Very much required. 26 | _make_visible(false) 27 | 28 | #this fixed nothing and i dont know why. 29 | #EditorInterface.get_editor_settings().set_setting("text_editor/behavior/files/auto_reload_scripts_on_external_change", true) 30 | #push_warning("(FACS ADDON): Force set the script editor to auto reload when changed to deal with compiler causing the \"newer on disk\" popup.") 31 | 32 | 33 | 34 | func initialize_resources()->void: 35 | if !DirAccess.dir_exists_absolute("res://FACS"): 36 | DirAccess.make_dir_absolute("res://FACS") 37 | if !DirAccess.dir_exists_absolute("res://FACS/Editor/"): 38 | DirAccess.make_dir_absolute("res://FACS/Editor/") 39 | if !DirAccess.dir_exists_absolute("res://FACS/Compiled/"): 40 | DirAccess.make_dir_absolute("res://FACS/Compiled/") 41 | if !FileAccess.file_exists("res://FACS/FACSManager.res"): 42 | var fMan=FACSManagerResource.new() 43 | fMan.resave() 44 | 45 | 46 | 47 | 48 | 49 | 50 | func _exit_tree(): 51 | remove_import_plugin(import_plugin_animation) 52 | remove_import_plugin(import_plugin_group) 53 | import_plugin_animation=null 54 | import_plugin_group=null 55 | if main_panel_instance: 56 | main_panel_instance.queue_free() 57 | 58 | 59 | func _has_main_screen(): 60 | return true 61 | 62 | 63 | func _make_visible(visible): 64 | if main_panel_instance: 65 | main_panel_instance.visible = visible 66 | get_editor_interface().distraction_free_mode=visible 67 | 68 | 69 | 70 | func _get_plugin_name(): 71 | return "FACS Animations" 72 | 73 | 74 | func _get_plugin_icon(): 75 | return EditorInterface.get_editor_theme().get_icon("Node", "EditorIcons") 76 | -------------------------------------------------------------------------------- /addons/FancyControls/FancyControls.gd.uid: -------------------------------------------------------------------------------- 1 | uid://dw7ud42ukwmyg 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/Add.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/Add.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://dpg38vn1xewp4" 6 | path="res://.godot/imported/Add.svg-8ea15f4e42af7eb07ada45f75c32cc80.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/FancyControls/GUI/Add.svg" 14 | dest_files=["res://.godot/imported/Add.svg-8ea15f4e42af7eb07ada45f75c32cc80.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/AssetLib.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/AssetLib.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://dgpk0ohyinq06" 6 | path="res://.godot/imported/AssetLib.svg-e408bfdfbe9bf81daa230ac4fd9cae89.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/FancyControls/GUI/AssetLib.svg" 14 | dest_files=["res://.godot/imported/AssetLib.svg-e408bfdfbe9bf81daa230ac4fd9cae89.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/GUItheme.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Theme" load_steps=15 format=3 uid="uid://bp4s6eux6tmj4"] 2 | 3 | [sub_resource type="StyleBoxTexture" id="StyleBoxTexture_0k450"] 4 | 5 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_38dvb"] 6 | bg_color = Color(0.054902, 0.133333, 0.188235, 1) 7 | border_color = Color(0.054902, 0.133333, 0.188235, 1) 8 | corner_radius_top_left = 8 9 | corner_radius_top_right = 8 10 | corner_radius_bottom_right = 8 11 | corner_radius_bottom_left = 8 12 | anti_aliasing = false 13 | 14 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_6lewo"] 15 | bg_color = Color(0.168627, 0.32549, 0.431373, 0.803922) 16 | border_width_left = 2 17 | border_width_right = 2 18 | border_width_bottom = 2 19 | border_color = Color(0.105882, 0.219608, 0.298039, 0.498039) 20 | corner_radius_bottom_right = 4 21 | corner_radius_bottom_left = 4 22 | anti_aliasing = false 23 | 24 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_is8xe"] 25 | bg_color = Color(0.25098, 0.45098, 0.588235, 0.803922) 26 | border_width_left = 2 27 | border_width_right = 2 28 | border_width_bottom = 2 29 | border_color = Color(0.105882, 0.219608, 0.298039, 0.498039) 30 | corner_radius_bottom_right = 4 31 | corner_radius_bottom_left = 4 32 | anti_aliasing = false 33 | 34 | [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_uxnsj"] 35 | 36 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_1ic5b"] 37 | bg_color = Color(0.14902, 0.290196, 0.388235, 0.803922) 38 | border_width_left = 2 39 | border_width_top = 2 40 | border_width_right = 2 41 | border_width_bottom = 2 42 | border_color = Color(0.105882, 0.219608, 0.298039, 0.498039) 43 | corner_radius_top_left = 4 44 | corner_radius_top_right = 4 45 | anti_aliasing = false 46 | 47 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_vkryl"] 48 | bg_color = Color(0.576868, 0.759417, 0.891963, 0.803922) 49 | border_width_left = 2 50 | border_width_top = 2 51 | border_width_right = 2 52 | border_width_bottom = 2 53 | border_color = Color(0.105882, 0.219608, 0.298039, 0.498039) 54 | corner_radius_top_left = 4 55 | corner_radius_top_right = 4 56 | anti_aliasing = false 57 | 58 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_6ettq"] 59 | bg_color = Color(0.054902, 0.133333, 0.188235, 1) 60 | border_color = Color(0.054902, 0.133333, 0.188235, 1) 61 | corner_radius_top_left = 4 62 | corner_radius_top_right = 4 63 | corner_radius_bottom_right = 4 64 | corner_radius_bottom_left = 4 65 | anti_aliasing = false 66 | 67 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_wpva2"] 68 | bg_color = Color(0.168627, 0.32549, 0.431373, 0.803922) 69 | border_color = Color(0.105882, 0.219608, 0.298039, 0.498039) 70 | corner_radius_top_left = 4 71 | corner_radius_top_right = 4 72 | corner_radius_bottom_right = 4 73 | corner_radius_bottom_left = 4 74 | anti_aliasing = false 75 | 76 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_0447o"] 77 | bg_color = Color(0.0938634, 0.194116, 0.270539, 1) 78 | 79 | [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ctsry"] 80 | bg_color = Color(0.0313726, 0.0941176, 0.141176, 1) 81 | corner_radius_top_left = 4 82 | corner_radius_top_right = 4 83 | corner_radius_bottom_right = 4 84 | corner_radius_bottom_left = 4 85 | 86 | [sub_resource type="Image" id="Image_uvyx6"] 87 | data = { 88 | "data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 76, 255, 255, 255, 75, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 99, 255, 255, 255, 191, 255, 255, 255, 191, 255, 255, 255, 99, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 4, 255, 255, 255, 122, 255, 255, 255, 191, 255, 255, 255, 188, 255, 255, 255, 188, 255, 255, 255, 191, 255, 255, 255, 121, 255, 255, 255, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 12, 255, 255, 255, 142, 255, 255, 255, 191, 255, 255, 255, 181, 255, 255, 255, 53, 255, 255, 255, 54, 255, 255, 255, 181, 255, 255, 255, 191, 255, 255, 255, 142, 255, 255, 255, 12, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 71, 255, 255, 255, 191, 255, 255, 255, 171, 255, 255, 255, 36, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 36, 255, 255, 255, 171, 255, 255, 255, 191, 255, 255, 255, 71, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 86, 255, 255, 255, 22, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 22, 255, 255, 255, 86, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 86, 255, 255, 255, 22, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 22, 255, 255, 255, 86, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 71, 255, 255, 255, 191, 255, 255, 255, 171, 255, 255, 255, 36, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 36, 255, 255, 255, 171, 255, 255, 255, 191, 255, 255, 255, 71, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 12, 255, 255, 255, 142, 255, 255, 255, 191, 255, 255, 255, 181, 255, 255, 255, 54, 255, 255, 255, 54, 255, 255, 255, 182, 255, 255, 255, 191, 255, 255, 255, 142, 255, 255, 255, 12, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 4, 255, 255, 255, 121, 255, 255, 255, 191, 255, 255, 255, 188, 255, 255, 255, 188, 255, 255, 255, 191, 255, 255, 255, 121, 255, 255, 255, 4, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 98, 255, 255, 255, 191, 255, 255, 255, 191, 255, 255, 255, 98, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 75, 255, 255, 255, 75, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0), 89 | "format": "RGBA8", 90 | "height": 16, 91 | "mipmaps": false, 92 | "width": 16 93 | } 94 | 95 | [sub_resource type="ImageTexture" id="ImageTexture_t2oep"] 96 | image = SubResource("Image_uvyx6") 97 | 98 | [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_eqoa4"] 99 | content_margin_left = 8.0 100 | content_margin_right = 8.0 101 | 102 | [resource] 103 | CodeEdit/colors/background_color = Color(0.0938634, 0.194116, 0.270539, 1) 104 | CodeEdit/colors/bookmark_color = Color(0.341176, 0.568627, 0.729412, 1) 105 | CodeEdit/colors/brace_mismatch_color = Color(0.564706, 0.156863, 0.141176, 1) 106 | CodeEdit/colors/breakpoint_color = Color(1, 1, 1, 1) 107 | CodeEdit/colors/caret_background_color = Color(1, 1, 1, 1) 108 | CodeEdit/colors/caret_color = Color(1, 1, 1, 1) 109 | CodeEdit/colors/code_folding_color = Color(1, 1, 1, 1) 110 | CodeEdit/colors/completion_background_color = Color(0, 0, 0, 1) 111 | CodeEdit/colors/completion_existing_color = Color(0, 0, 0, 1) 112 | CodeEdit/colors/completion_scroll_color = Color(0, 0, 0, 1) 113 | CodeEdit/colors/completion_scroll_hovered_color = Color(0, 0, 0, 1) 114 | CodeEdit/colors/completion_selected_color = Color(0, 0, 0, 1) 115 | CodeEdit/colors/current_line_color = Color(0, 0, 0, 1) 116 | CodeEdit/colors/executing_line_color = Color(0, 0, 0, 1) 117 | CodeEdit/colors/folded_code_region_color = Color(0, 0, 0, 1) 118 | CodeEdit/colors/font_color = Color(0, 0, 0, 1) 119 | CodeEdit/colors/font_outline_color = Color(0, 0, 0, 1) 120 | CodeEdit/colors/font_placeholder_color = Color(0, 0, 0, 1) 121 | CodeEdit/colors/font_readonly_color = Color(0.792157, 0.529412, 0.611765, 1) 122 | CodeEdit/colors/font_selected_color = Color(0.917647, 0.780392, 0.819608, 1) 123 | CodeEdit/colors/line_length_guideline_color = Color(1, 1, 1, 1) 124 | CodeEdit/colors/line_number_color = Color(0.466667, 0.254902, 0.32549, 1) 125 | CodeEdit/colors/search_result_border_color = Color(0, 0, 0, 1) 126 | CodeEdit/colors/search_result_color = Color(0, 0, 0, 1) 127 | CodeEdit/colors/selection_color = Color(0.341176, 0.568627, 0.729412, 0.494118) 128 | CodeEdit/colors/word_highlighted_color = Color(0, 0, 0, 1) 129 | CodeEdit/constants/completion_lines = 0 130 | CodeEdit/constants/completion_max_width = 0 131 | CodeEdit/constants/completion_scroll_width = 0 132 | CodeEdit/constants/line_spacing = 0 133 | CodeEdit/constants/outline_size = 0 134 | CodeEdit/font_sizes/font_size = 16 135 | CodeEdit/fonts/font = null 136 | CodeEdit/icons/bookmark = null 137 | CodeEdit/icons/breakpoint = null 138 | CodeEdit/icons/can_fold = null 139 | CodeEdit/icons/can_fold_code_region = null 140 | CodeEdit/icons/executing_line = null 141 | CodeEdit/icons/folded = null 142 | CodeEdit/icons/folded_code_region = null 143 | CodeEdit/icons/folded_eol_icon = null 144 | CodeEdit/icons/space = null 145 | CodeEdit/icons/tab = null 146 | CodeEdit/styles/completion = null 147 | CodeEdit/styles/focus = null 148 | CodeEdit/styles/normal = null 149 | CodeEdit/styles/read_only = null 150 | GraphEdit/colors/activity = Color(0, 0, 0, 1) 151 | GraphEdit/colors/grid_major = Color(0.104765, 0.21771, 0.296853, 1) 152 | GraphEdit/colors/grid_minor = Color(0.0313726, 0.0941176, 0.141176, 1) 153 | GraphEdit/colors/selection_fill = Color(0.403922, 0.631373, 0.792157, 0.184314) 154 | GraphEdit/colors/selection_stroke = Color(0.192157, 0.360784, 0.478431, 0.631373) 155 | GraphEdit/constants/port_hotzone_inner_extent = 4 156 | GraphEdit/constants/port_hotzone_outer_extent = 4 157 | GraphEdit/icons/grid_toggle = null 158 | GraphEdit/icons/layout = null 159 | GraphEdit/icons/minimap_toggle = null 160 | GraphEdit/icons/snapping_toggle = null 161 | GraphEdit/icons/zoom_in = null 162 | GraphEdit/icons/zoom_out = null 163 | GraphEdit/icons/zoom_reset = null 164 | GraphEdit/styles/menu_panel = SubResource("StyleBoxTexture_0k450") 165 | GraphEdit/styles/panel = SubResource("StyleBoxFlat_38dvb") 166 | GraphNode/colors/resizer_color = Color(0, 0, 0, 1) 167 | GraphNode/constants/port_h_offset = -5 168 | GraphNode/constants/separation = 0 169 | GraphNode/icons/port = null 170 | GraphNode/icons/resizer = null 171 | GraphNode/styles/panel = SubResource("StyleBoxFlat_6lewo") 172 | GraphNode/styles/panel_selected = SubResource("StyleBoxFlat_is8xe") 173 | GraphNode/styles/slot = SubResource("StyleBoxEmpty_uxnsj") 174 | GraphNode/styles/titlebar = SubResource("StyleBoxFlat_1ic5b") 175 | GraphNode/styles/titlebar_selected = SubResource("StyleBoxFlat_vkryl") 176 | GraphNodeTitleLabel/colors/font_color = Color(0.827451, 0.886275, 1, 1) 177 | GraphNodeTitleLabel/colors/font_outline_color = Color(0, 0, 0, 1) 178 | GraphNodeTitleLabel/colors/font_shadow_color = Color(0, 0, 0, 1) 179 | GraphNodeTitleLabel/constants/line_spacing = 0 180 | GraphNodeTitleLabel/constants/outline_size = 0 181 | GraphNodeTitleLabel/constants/shadow_offset_x = 0 182 | GraphNodeTitleLabel/constants/shadow_offset_y = 0 183 | GraphNodeTitleLabel/constants/shadow_outline_size = 0 184 | GraphNodeTitleLabel/font_sizes/font_size = 16 185 | GraphNodeTitleLabel/fonts/font = null 186 | GraphNodeTitleLabel/styles/normal = null 187 | ItemList/colors/font_color = Color(0.180385, 0.346591, 0.470802, 1) 188 | ItemList/colors/font_hovered_color = Color(0.244234, 0.445088, 0.595982, 1) 189 | ItemList/colors/font_outline_color = Color(0, 0, 0, 1) 190 | ItemList/colors/font_selected_color = Color(1, 1, 1, 1) 191 | ItemList/colors/guide_color = Color(0.0313726, 0.0941176, 0.141176, 1) 192 | ItemList/constants/h_separation = 0 193 | ItemList/constants/icon_margin = 0 194 | ItemList/constants/line_separation = 0 195 | ItemList/constants/outline_size = 0 196 | ItemList/constants/v_separation = 0 197 | ItemList/font_sizes/font_size = 20 198 | ItemList/fonts/font = null 199 | ItemList/styles/cursor = null 200 | ItemList/styles/cursor_unfocused = null 201 | ItemList/styles/focus = SubResource("StyleBoxFlat_6ettq") 202 | ItemList/styles/hovered = SubResource("StyleBoxFlat_wpva2") 203 | ItemList/styles/panel = SubResource("StyleBoxFlat_6ettq") 204 | ItemList/styles/selected = SubResource("StyleBoxFlat_wpva2") 205 | ItemList/styles/selected_focus = SubResource("StyleBoxFlat_wpva2") 206 | Label/colors/font_color = Color(1, 1, 1, 1) 207 | Label/colors/font_outline_color = Color(0, 0, 0, 1) 208 | Label/colors/font_shadow_color = Color(0.0313726, 0.0941176, 0.141176, 1) 209 | Label/constants/line_spacing = 0 210 | Label/constants/outline_size = 0 211 | Label/constants/shadow_offset_x = 0 212 | Label/constants/shadow_offset_y = 0 213 | Label/constants/shadow_outline_size = 0 214 | Label/font_sizes/font_size = 16 215 | Label/fonts/font = null 216 | Label/styles/normal = null 217 | LineEdit/colors/caret_color = Color(1, 1, 1, 1) 218 | LineEdit/colors/clear_button_color = Color(1, 1, 1, 1) 219 | LineEdit/colors/clear_button_color_pressed = Color(1, 1, 1, 1) 220 | LineEdit/colors/font_color = Color(0.341176, 0.568627, 0.729412, 1) 221 | LineEdit/colors/font_outline_color = Color(1, 1, 1, 1) 222 | LineEdit/colors/font_placeholder_color = Color(0.254902, 0.458824, 0.6, 1) 223 | LineEdit/colors/font_selected_color = Color(0.658824, 0.658824, 0.658824, 1) 224 | LineEdit/colors/font_uneditable_color = Color(0.0390073, 0.10289, 0.151539, 1) 225 | LineEdit/colors/selection_color = Color(0.572549, 0.752941, 0.890196, 0.215686) 226 | LineEdit/constants/caret_width = 1 227 | LineEdit/constants/minimum_character_width = 0 228 | LineEdit/constants/outline_size = 0 229 | LineEdit/font_sizes/font_size = 16 230 | LineEdit/fonts/font = null 231 | LineEdit/icons/clear = null 232 | LineEdit/styles/focus = SubResource("StyleBoxFlat_0447o") 233 | LineEdit/styles/normal = SubResource("StyleBoxFlat_0447o") 234 | LineEdit/styles/read_only = SubResource("StyleBoxFlat_0447o") 235 | PanelContainer/styles/panel = SubResource("StyleBoxFlat_ctsry") 236 | SpinBox/icons/updown = SubResource("ImageTexture_t2oep") 237 | TabBar/colors/drop_mark_color = Color(0, 0, 0, 1) 238 | TabBar/colors/font_disabled_color = Color(0.0938634, 0.194116, 0.270539, 1) 239 | TabBar/colors/font_hovered_color = Color(0.349233, 0.576134, 0.738801, 1) 240 | TabBar/colors/font_outline_color = Color(0, 0, 0, 1) 241 | TabBar/colors/font_selected_color = Color(1, 1, 1, 1) 242 | TabBar/colors/font_unselected_color = Color(0.273779, 0.482478, 0.630363, 1) 243 | TabBar/constants/h_separation = 0 244 | TabBar/constants/icon_max_width = 0 245 | TabBar/constants/outline_size = 0 246 | TabBar/font_sizes/font_size = 20 247 | TabBar/fonts/font = null 248 | TabBar/icons/close = null 249 | TabBar/icons/decrement = null 250 | TabBar/icons/decrement_highlight = null 251 | TabBar/icons/drop_mark = null 252 | TabBar/icons/increment = null 253 | TabBar/icons/increment_highlight = null 254 | TabBar/styles/button_highlight = SubResource("StyleBoxEmpty_eqoa4") 255 | TabBar/styles/button_pressed = SubResource("StyleBoxEmpty_eqoa4") 256 | TabBar/styles/tab_disabled = SubResource("StyleBoxEmpty_eqoa4") 257 | TabBar/styles/tab_focus = SubResource("StyleBoxEmpty_eqoa4") 258 | TabBar/styles/tab_hovered = SubResource("StyleBoxEmpty_eqoa4") 259 | TabBar/styles/tab_selected = SubResource("StyleBoxEmpty_eqoa4") 260 | TabBar/styles/tab_unselected = SubResource("StyleBoxEmpty_eqoa4") 261 | Tree/constants/inner_item_margin_bottom = 0 262 | Tree/constants/inner_item_margin_left = 0 263 | Tree/constants/inner_item_margin_right = 0 264 | Tree/constants/inner_item_margin_top = 0 265 | Tree/constants/item_margin = 0 266 | spinbox_hider/base_type = &"LineEdit" 267 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/block/BlockColoring.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends RefCounted 3 | class_name BlockColoring 4 | 5 | 6 | static func ChangePortType(node:GraphNode,slot:int,side:int,type:int)->void: 7 | node.set_meta(&"type_%s"%str(slot),type) 8 | match type: 9 | TYPE_FLOAT: 10 | if side%2==1 and node.is_slot_enabled_left(slot): 11 | node.set_slot_type_left(slot,type) 12 | node.set_slot_color_left(slot,Color('FFF169')) 13 | if side>1 and node.is_slot_enabled_right(slot): 14 | node.set_slot_type_right(slot,type) 15 | node.set_slot_color_right(slot,Color('FFF169')) 16 | TYPE_VECTOR2: 17 | if side%2==1 and node.is_slot_enabled_left(slot): 18 | node.set_slot_type_left(slot,type) 19 | node.set_slot_color_left(slot,Color('73ff73')) 20 | if side>1 and node.is_slot_enabled_right(slot): 21 | node.set_slot_type_right(slot,type) 22 | node.set_slot_color_right(slot,Color('73ff73')) 23 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/block/BlockColoring.gd.uid: -------------------------------------------------------------------------------- 1 | uid://bxtr5wulba27x 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/block/BlockList.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends Tree 3 | 4 | 5 | 6 | ##gonna use a custom _get_property_list() method to work on this and make it easier to work with 7 | @export var BlockList:CodeBlockListResource 8 | 9 | var blocks:Array[CodeBlockResource]: 10 | get:return BlockList.block_list 11 | 12 | var categories:Dictionary={} 13 | 14 | var root_item:TreeItem 15 | 16 | func _ready(): 17 | clear() 18 | root_item=create_item() 19 | 20 | load_blocks_into_list() 21 | 22 | func load_blocks_into_list()->void: 23 | for block in blocks: 24 | ensure_categories_loaded(block) 25 | add_block_to_categories(block) 26 | 27 | 28 | func ensure_categories_loaded(block)->void: 29 | for category in block.BlockCategories: 30 | if categories.has(category):continue 31 | var category_item = root_item.create_child() 32 | category_item.set_text(0,category) 33 | categories[category]=category_item 34 | 35 | func add_block_to_categories(block)->void: 36 | for category in block.BlockCategories: 37 | var block_item = categories[category].create_child() 38 | block_item.set_text(0,block.BlockName) 39 | block_item.set_meta("SourceRef",block) 40 | 41 | 42 | func search_items(search_string:String="",search_category:String="")->void: 43 | 44 | search_string=search_string.to_lower() 45 | search_category=search_category.to_lower() 46 | var used_list:=blocks.filter(func(block): 47 | return (search_category=="any"||block.BlockCategories.has(search_category.to_lower())) and (block.BlockName.to_lower().contains(search_string)||search_string=="") 48 | ) 49 | 50 | 51 | func _on_item_selected(): 52 | ##code that allows me to collapse all but the current relevant category group 53 | #var chosen_item=get_selected() 54 | #while chosen_item.get_parent()!=root_item: 55 | #chosen_item=chosen_item.get_parent() 56 | # 57 | #for item in root_item.get_children(): 58 | #item.collapsed=item!=get_selected() 59 | 60 | 61 | if get_selected().get_parent()==root_item:return 62 | 63 | var name_of_block=get_selected().get_text(0) 64 | if not blocks.any(func(v):return v.BlockName==name_of_block):return 65 | create_item_block(name_of_block) 66 | 67 | 68 | func create_item_block(name_of_block,select:bool=true,attach_to:Node=null): 69 | 70 | var added_block=blocks.filter(func(v):return v.BlockName==name_of_block)[0].build_block() 71 | 72 | #compiles info as needed to re-link cause it hates me 73 | for child in added_block.get_children(): 74 | for options in child.get_children(): 75 | if options.has_meta(&"link"): 76 | var link_info=options.get_meta(&"link") 77 | options.connect(link_info[0],link_info[2].bind(added_block)) 78 | item_block_func.call_deferred(options,link_info,added_block,child) 79 | options.remove_meta(&"link") 80 | added_block.disconnected_port.connect(func(id,node): 81 | id-=int(node.get_parent().get_meta(&"runnable",false)) 82 | if added_block.has_meta(&"default_%s"%str(id)): 83 | added_block.set_meta(&"value_%s"%str(id),added_block.get_meta(&"default_%s"%str(id))) 84 | if added_block.has_meta(&"reset_type_%s"%str(id)): 85 | added_block.set_meta(&"type_%s"%str(id),added_block.get_meta(&"reset_type_%s"%str(id))) 86 | ) 87 | if attach_to==null:attach_to=$"../../BlockUI" 88 | attach_to.attach_node(added_block) 89 | if !select:return added_block 90 | await get_tree().process_frame 91 | if attach_to==$"../../BlockUI": 92 | $"../../BlockUI".set_selected(added_block) 93 | $"../../BlockUI".grab_focus() 94 | added_block.position_offset=($"../../BlockUI".scroll_offset+$"../../BlockUI".size*0.5-added_block.size*0.5-size*Vector2(0.5,0))/$"../../BlockUI".zoom 95 | return added_block 96 | 97 | 98 | func item_block_func(options,link_info,added_block,child): 99 | await get_tree().process_frame 100 | var ind=added_block.get_children().find(child)-int(added_block.get_meta(&"runnable")) 101 | if options.has_meta(&"reset_value"): 102 | added_block.connect("disconnected_port",func(v,b): 103 | if b==options.get_parent(): 104 | added_block.set_meta(&"value_%s"%str(ind),options.get_meta(&"reset_value")) 105 | ) 106 | 107 | if added_block.has_meta(&"value_%s"%str(ind)): 108 | var val=added_block.get_meta(&"value_%s"%str(ind)) 109 | if options is SpinBox and val is Vector2: 110 | 111 | options.value=val[int(options.get_parent().get_children().find(options))-1] 112 | if options is OptionButton: 113 | for item in options.item_count: 114 | if val.ends_with(options.get_item_text(item)): 115 | options.select(item);break 116 | 117 | if options is SpinBox and val is float: 118 | options.value=val 119 | if options is LineEdit and val is String: 120 | options.text=val 121 | return options.emit_signal(link_info[0],val) 122 | options.emit_signal(link_info[0],link_info[1]) 123 | 124 | 125 | 126 | 127 | 128 | func _on_option_button_item_selected(index): 129 | var a=OptionButton.new() 130 | 131 | search_items($"../HBoxContainer/LineEdit".text,$"../HBoxContainer/OptionButton".get_item_text($"../HBoxContainer/OptionButton".get_selected_id())) 132 | 133 | 134 | func _on_line_edit_text_changed(new_text): 135 | search_items($"../HBoxContainer/LineEdit".text,$"../HBoxContainer/OptionButton".get_item_text($"../HBoxContainer/OptionButton".get_selected_id())) 136 | 137 | #used to manage double clicking to expand and shrink the block type list 138 | func _on_item_activated(): 139 | if get_selected().get_parent()!=root_item:return 140 | get_selected().collapsed=!get_selected().collapsed 141 | 142 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/block/BlockList.gd.uid: -------------------------------------------------------------------------------- 1 | uid://cng7ur0r6o73l 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/block/BlockListResource.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends Resource 3 | class_name CodeBlockListResource 4 | 5 | @export var block_list:Array[CodeBlockResource]=[] 6 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/block/BlockListResource.gd.uid: -------------------------------------------------------------------------------- 1 | uid://bqahd4r2sue7t 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/block/BlockUI.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends GraphEdit 3 | @onready var code_funcs=code_block_funcs.new() 4 | 5 | 6 | var undo:UndoRedo=UndoRedo.new() 7 | 8 | var connection_map:Dictionary={} 9 | 10 | 11 | # Called when the node enters the scene tree for the first time. 12 | func _ready(): 13 | 14 | $StartNode.set_meta(&"runnable",true) 15 | $StartNode.set_meta(&"type","function") 16 | $StartNode.set_meta(&"action","INITIALIZE") 17 | $StartNode.set_meta(&"value_0","run_item_if_seen_it_is_an_error") 18 | $StartNode.set_meta(&"type_0",TYPE_NIL) 19 | $StartNode.set_meta(&"value_1","item_node.global_position") 20 | $StartNode.set_meta(&"type_1",TYPE_VECTOR2) 21 | $StartNode.set_meta(&"value_2","item_node.scale") 22 | $StartNode.set_meta(&"type_2",TYPE_VECTOR2) 23 | $StartNode.set_meta(&"value_3","item_node.rotation") 24 | $StartNode.set_meta(&"type_3",TYPE_FLOAT) 25 | $StartNode.set_meta(&"value_4","item_index") 26 | $StartNode.set_meta(&"type_4",TYPE_INT) 27 | $StartNode.set_meta(&"value_5","total_items") 28 | $StartNode.set_meta(&"type_5",TYPE_INT) 29 | $StartNode.set_meta(&"value_count",4) 30 | $StartNode.set_meta(&"ignore_in_compile",true) 31 | 32 | $StartContainerNode.set_meta(&"runnable",false) 33 | $StartContainerNode.set_meta(&"type","function") 34 | $StartContainerNode.set_meta(&"action","INITIALIZE_CONTAINER") 35 | $StartContainerNode.set_meta(&"value_0","container_info.size") 36 | $StartContainerNode.set_meta(&"type_0",TYPE_VECTOR2) 37 | $StartContainerNode.set_meta(&"value_1","container_info.global_position") 38 | $StartContainerNode.set_meta(&"type_1",TYPE_VECTOR2) 39 | $StartContainerNode.set_meta(&"value_2","container_info.item_origins[item_index]") 40 | $StartContainerNode.set_meta(&"type_2",TYPE_VECTOR2) 41 | $StartContainerNode.set_meta(&"value_3","container_info.rotation") 42 | $StartContainerNode.set_meta(&"type_3",TYPE_FLOAT) 43 | $StartContainerNode.set_meta(&"value_count",4) 44 | $StartContainerNode.set_meta(&"ignore_in_compile",true) 45 | 46 | 47 | 48 | set_meta(&"func_name","unset_name") 49 | 50 | 51 | add_valid_connection_type(0,0) 52 | add_valid_connection_type(TYPE_FLOAT,TYPE_VECTOR2) 53 | add_valid_connection_type(TYPE_VECTOR2,TYPE_FLOAT) 54 | 55 | 56 | 57 | func _input(event): 58 | if event is InputEventKey and event.as_text()=="Ctrl+Z" and event.is_pressed() and not event.is_echo(): 59 | 60 | undo.undo() 61 | if event is InputEventKey and event.as_text()=="Ctrl+Shift+Z" and event.is_pressed() and not event.is_echo(): 62 | undo.redo() 63 | 64 | 65 | 66 | 67 | func generate_connection_map()->void: 68 | connection_map={} 69 | connections.map(map_connection) 70 | func map_connection(connection)->void: 71 | var connection_data=connection_map.get(connection.from_node,[]) 72 | connection_data.push_back( 73 | { 74 | "from":get_node(String(connection.from_node)), 75 | "to":get_node(String(connection.to_node)), 76 | "from_port":connection.from_port, 77 | "to_port":connection.to_port 78 | } 79 | ) 80 | connection_map.set(connection.from_node,connection_data) 81 | 82 | 83 | 84 | func _on_connection_request(from_node, from_port, to_node, to_port): 85 | 86 | undo.create_action("UndoConnection") 87 | undo.add_do_method(connection_request_logic.bind(from_node,from_port,to_node,to_port)) 88 | undo.add_undo_method(disconnection_request_logic.bind(from_node,from_port,to_node,to_port)) 89 | undo.commit_action() 90 | 91 | func connection_request_logic(from_node,from_port,to_node,to_port): 92 | if code_funcs==null:code_funcs=code_block_funcs.new() 93 | generate_connection_map() 94 | #hide the editable section when it is set externally 95 | var from_block = get_block(from_node) 96 | var to_block = get_block(to_node) 97 | 98 | var node_port=to_block.get_child(to_block.get_input_port_slot(to_port)) 99 | var connection_list=connection_map.get(from_node,[]) 100 | 101 | #actions can only chain 102 | if from_block.get_meta(&"runnable") and from_port==0 and connection_list.any(check_from_connected.bind(from_block,from_port)):return 103 | if connection_list.any(check_to_connected.bind(to_block,to_port)):return 104 | 105 | var to_port_slot=to_block.get_input_port_slot(to_port) 106 | var from_port_slot=from_block.get_output_port_slot(from_port) 107 | if to_block.has_meta(&"SourceRef"): 108 | var ref = to_block.get_meta(&"SourceRef",null) 109 | if ref:ref.value_changed.call_deferred(to_block,to_port_slot,true) 110 | if from_block.has_meta(&"SourceRef"): 111 | var ref=from_block.get_meta(&"SourceRef",null) 112 | if ref:ref.value_changed.call_deferred(from_block,from_port_slot,true) 113 | 114 | 115 | 116 | if to_port_slot>0: 117 | to_block.set_meta( 118 | &"value_%s"%str(to_port_slot), 119 | get_port_value(from_node,from_block,from_port) 120 | ) 121 | 122 | 123 | var check_methods=[ 124 | str(from_block.get_meta(&"action")).to_lower()+"_connected", 125 | str(to_block.get_meta(&"action")).to_lower()+"_connected" 126 | ] 127 | for method_name in check_methods: 128 | if not code_funcs.has_method(method_name):continue 129 | code_funcs.call_deferred(method_name,from_node,to_node,from_port,to_port,self) 130 | 131 | 132 | if node_port.get_child_count()>1: 133 | for child in range(1,node_port.get_child_count()): 134 | node_port.get_child(child).hide() 135 | if node_port.get_child_count()>1:node_port.get_child(1).hide() 136 | 137 | connect_node(from_node,from_port,to_node,to_port) 138 | 139 | 140 | func get_block(block_name): 141 | return get_node_or_null(String(block_name)) 142 | func check_to_connected(from,to,to_port)->bool: 143 | return from.get("to",null)==to and from.get("to_port",-1) == to_port 144 | func check_from_connected(from,to,to_port)->bool: 145 | return from.get("from",null)==to and from.get("from_port",-1) == to_port 146 | 147 | func get_port_value(from_name:String,node_block,from_port:int)->String: 148 | return String(from_name)+"|value_%s"%node_block.get_output_port_slot(from_port) if not node_block.get_meta(&"type")=="variable" else String(from_name)+"|value_0" 149 | 150 | 151 | 152 | 153 | func _on_disconnection_request(from_node, from_port, to_node, to_port): 154 | 155 | undo.create_action("UndoDisconnection") 156 | undo.add_do_method(disconnection_request_logic.bind(from_node,from_port,to_node,to_port)) 157 | undo.add_undo_method(connection_request_logic.bind(from_node,from_port,to_node,to_port)) 158 | undo.commit_action() 159 | 160 | 161 | func disconnection_request_logic(from_node,from_port,to_node,to_port): 162 | generate_connection_map() 163 | 164 | var from_block = get_block(from_node) 165 | var to_block = get_block(to_node) 166 | 167 | var to_port_slot=to_block.get_input_port_slot(to_port) 168 | var node_port=to_block.get_child(to_port_slot) 169 | 170 | #hide the editable section when it is set externally 171 | to_block.emit_signal("disconnected_port",to_port_slot,node_port) 172 | 173 | if node_port.get_child_count()>1: 174 | for child in range(1,node_port.get_child_count()): 175 | node_port.get_child(child).show() 176 | disconnect_node(from_node,from_port,to_node,to_port) 177 | 178 | var source_ref=to_block.get_meta(&"SourceRef") 179 | if source_ref:source_ref.reset_value(to_block, 180 | to_port_slot,to_block.get_meta(&"runnable",false) 181 | ) 182 | 183 | 184 | var check_methods=[ 185 | str(from_block.get_meta(&"action")).to_lower()+"_disconnected", 186 | str(to_block.get_meta(&"action")).to_lower()+"_disconnected" 187 | ] 188 | for method_name in check_methods: 189 | if not code_funcs.has_method(method_name):continue 190 | code_funcs.call_deferred(method_name,from_node,to_node,from_port,to_port,self) 191 | 192 | 193 | 194 | 195 | func _on_delete_nodes_request(nodes): 196 | #to block removing the start node that is treated as the start for parsing 197 | var start_at=nodes.find(&"StartNode") 198 | if start_at>-1:nodes.remove_at(start_at) 199 | start_at=nodes.find(&"StartContainerNode") 200 | if start_at>-1:nodes.remove_at(start_at) 201 | 202 | undo.create_action("UndoDeleteNodes") 203 | 204 | 205 | for node in nodes: 206 | var grabbed = get_node(String(node)) 207 | undo.add_undo_reference(grabbed) 208 | 209 | undo.add_undo_method(add_child.bind(grabbed)) 210 | get_connection_list().map(func(v):if v.from_node==node||v.to_node==node: 211 | undo.add_do_method(disconnection_request_logic.bind(v.from_node,v.from_port,v.to_node,v.to_port)) 212 | undo.add_undo_method(call_deferred.bind('connection_request_logic',v.from_node,v.from_port,v.to_node,v.to_port)) 213 | ) 214 | undo.add_do_method( 215 | undo_delete_method.bind(grabbed) 216 | ) 217 | 218 | undo.commit_action.call_deferred() 219 | 220 | func undo_delete_method(grabbed): 221 | await get_tree().process_frame 222 | call_deferred("remove_child",grabbed) 223 | 224 | 225 | 226 | var current_selected_nodes:Array=[] 227 | 228 | func _on_duplicate_nodes_request(): 229 | for node in current_selected_nodes: 230 | if node.name=="StartNode" or node.name=="StartContainerNode":continue 231 | #need to create new nodes to keep functions working because they seem to hate lambdas connected to signals i guess 232 | 233 | 234 | 235 | func _on_node_selected(node): 236 | current_selected_nodes.push_back(node) 237 | 238 | 239 | func _on_node_deselected(node): 240 | current_selected_nodes.erase(node) 241 | 242 | 243 | func _on_func_name_text_changed(new_text): 244 | set_meta(&"func_name",new_text) 245 | 246 | 247 | func _on_begin_node_move(): 248 | undo.create_action("UndoMoveNodes") 249 | for node in current_selected_nodes: 250 | undo.add_undo_property(node,"position_offset",node.position_offset) 251 | 252 | 253 | func _on_end_node_move(): 254 | for node in current_selected_nodes: 255 | undo.add_do_property(node,"position_offset",node.position_offset) 256 | undo.commit_action() 257 | 258 | 259 | ## because undo-redo is always a nice feature to have, this acts as the builder to call 260 | ## instead of add_child in the blocklist when creating one 261 | func attach_node(child)->void: 262 | undo.create_action("UndoCreateNode") 263 | undo.add_do_reference(child) 264 | undo.add_do_method(add_child.bind(child)) 265 | undo.add_undo_method(remove_child.bind(child)) 266 | undo.add_undo_method(_on_node_deselected.bind(child)) 267 | undo.commit_action() 268 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/block/BlockUI.gd.uid: -------------------------------------------------------------------------------- 1 | uid://tmyfvw68lblc 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/block/CodeBlockLogic.gd: -------------------------------------------------------------------------------- 1 | extends RefCounted 2 | class_name CodeBlockLogic 3 | 4 | 5 | static func FloatParameter(new_value,block,edit,param_id)->void: 6 | if not edit.visible:return 7 | if new_value is float:edit.value=new_value 8 | block.set_meta(&"value_%s"%str(param_id),new_value) 9 | 10 | static func Vector2Parameter(new_value,block,edit,param_id,is_value_y)->void: 11 | if not edit.visible:return 12 | if new_value is Vector2:new_value=new_value.y if is_value_y else new_value.x 13 | if new_value is float:edit.value=new_value 14 | var link_val=block.get_meta(&"value_%s"%str(param_id),Vector2.ZERO) 15 | if link_val is String:return 16 | var new_vector = ( 17 | Vector2(block.get_meta(&"value_%s"%str(param_id),Vector2.ZERO).x,new_value) 18 | if is_value_y else 19 | Vector2(new_value,block.get_meta(&"value_%s"%str(param_id),Vector2.ZERO).y) 20 | ) 21 | block.set_meta(&"value_%s"%str(param_id),new_vector) 22 | edit.value=new_value 23 | 24 | static func StringParameter(new_value,block,edit,param_id)->void: 25 | if not edit.visible:return 26 | if new_value is String: 27 | while new_value.begins_with("("): 28 | new_value=new_value.trim_prefix("(") 29 | edit.text=new_value 30 | block.set_meta(&"value_%s"%str(param_id),new_value) 31 | 32 | 33 | static func PackedStringArrayParameter(new_value,block,edit,param_id,default_value)->void: 34 | if new_value is int:new_value=edit.get_item_text(new_value) 35 | block.set_meta(&"value_%s"%str(param_id),new_value) 36 | 37 | 38 | static func BoolParameter(new_value,block,edit,param_id,default_value)->void: 39 | if not (new_value is bool):new_value=default_value 40 | block.set_meta(&"value_%s"%str(param_id),new_value) 41 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/block/CodeBlockLogic.gd.uid: -------------------------------------------------------------------------------- 1 | uid://kgpfqf7t70kg 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/block/CodeBlockParameters.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends Resource 3 | class_name CodeBlockParameters 4 | 5 | @export var ParameterName:String 6 | @export var ParameterType:Variant.Type: 7 | set(v): 8 | ParameterType=v 9 | notify_property_list_changed() 10 | @export var Editable:bool=true 11 | @export_enum( 12 | "Left", 13 | "Right" 14 | ) var PartOnSide=0 15 | 16 | @export var specialDefault:String="" 17 | @export var extra_resets:PackedInt32Array=PackedInt32Array([]) 18 | var DefaultValue 19 | 20 | 21 | func _get_property_list(): 22 | var result=[] 23 | var list_of_types:Array=[] 24 | for i in TYPE_MAX: 25 | list_of_types.push_back(type_string(i)) 26 | 27 | result.append( 28 | { 29 | &"name": "DefaultValue", 30 | &"type": ParameterType, 31 | &"usage": PROPERTY_USAGE_DEFAULT 32 | } 33 | ) 34 | return result 35 | 36 | 37 | func get_parts_for_block(built_block:Control,val:int=-1,port_id:int=-1)->void: 38 | var component = HBoxContainer.new() 39 | var lbl = Label.new() 40 | lbl.text=ParameterName 41 | component.add_child(lbl) 42 | match ParameterType: 43 | TYPE_INT: 44 | pass 45 | TYPE_FLOAT: 46 | if Editable: 47 | var edit=SpinBox.new() 48 | edit.allow_greater=true 49 | edit.allow_lesser=true 50 | edit.step=0.01 51 | component.add_child(edit) 52 | built_block.set_meta(&"value_%s"%str(port_id),DefaultValue) 53 | edit.set_meta(&"reset_value",DefaultValue) 54 | edit.value_changed.connect(CodeBlockLogic.FloatParameter.bind(built_block,edit,port_id)) 55 | edit.size_flags_horizontal=Control.SIZE_EXPAND_FILL 56 | BlockColoring.ChangePortType(built_block,port_id,PartOnSide,TYPE_FLOAT) 57 | 58 | TYPE_VECTOR2: 59 | BlockColoring.ChangePortType(built_block,port_id, 60 | PartOnSide, 61 | TYPE_VECTOR2 62 | ) 63 | if Editable: 64 | for i in 2: 65 | var edit=SpinBox.new() 66 | edit.allow_greater=true 67 | edit.allow_lesser=true 68 | edit.step=0.01 69 | component.add_child(edit) 70 | edit.set_meta(&"reset_value",DefaultValue.x if i == 0 else DefaultValue.y) 71 | edit.value_changed.connect(CodeBlockLogic.Vector2Parameter.bind(built_block,edit,port_id,i==1)) 72 | edit.size_flags_horizontal=Control.SIZE_EXPAND_FILL 73 | built_block.set_meta(&"value_%s"%str(port_id),DefaultValue) 74 | TYPE_STRING: 75 | var edit=LineEdit.new() 76 | component.add_child(edit) 77 | built_block.set_meta(&"value_%s"%str(port_id),DefaultValue) 78 | edit.size_flags_horizontal=Control.SIZE_EXPAND_FILL 79 | edit.text_changed.connect(CodeBlockLogic.StringParameter.bind(built_block,edit,port_id)) 80 | TYPE_PACKED_STRING_ARRAY: 81 | var edit=OptionButton.new() 82 | for item in len(DefaultValue)-1:edit.add_item(DefaultValue[item]) 83 | component.add_child(edit) 84 | built_block.set_meta(&"value_%s"%str(port_id),DefaultValue[0]) 85 | edit.item_selected.connect(CodeBlockLogic.PackedStringArrayParameter.bind(built_block,edit,port_id,DefaultValue)) 86 | edit.size_flags_horizontal=Control.SIZE_EXPAND_FILL 87 | 88 | TYPE_BOOL: 89 | var edit=CheckBox.new() 90 | component.add_child(edit) 91 | built_block.set_meta(&"value_%s"%str(port_id),DefaultValue) 92 | edit.toggled.connect(CodeBlockLogic.BoolParameter.bind(built_block,edit,port_id,DefaultValue)) 93 | edit.size_flags_horizontal=Control.SIZE_EXPAND_FILL 94 | apply_format_to_block(built_block,val,port_id,component) 95 | 96 | func apply_format_to_block(block:FACSGraphNode,val,port_id,component)->void: 97 | block.add_child(component) 98 | block.set_slot_enabled_left(port_id,PartOnSide==0) 99 | block.set_slot_enabled_right(port_id,PartOnSide==1) 100 | 101 | BlockColoring.ChangePortType(block,port_id,PartOnSide+1,ParameterType) 102 | 103 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/block/CodeBlockParameters.gd.uid: -------------------------------------------------------------------------------- 1 | uid://bjpuyvh056a74 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/block/block_funcs.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends Node 3 | class_name code_block_funcs 4 | 5 | #region value type getter. annoying code but it works for now. 6 | ##i'll improve it and move it later 7 | const default_value_types={ 8 | "item_node.rotation":TYPE_FLOAT, 9 | "item_node.position":TYPE_VECTOR2, 10 | "item_node.global_position":TYPE_VECTOR2, 11 | "item_node.scale":TYPE_VECTOR2, 12 | 13 | } 14 | func get_value_type(on_node:GraphNode,val:int=0): 15 | #loops until it hits the primary reference it is linked to 16 | var on_graph=on_node.get_parent() 17 | var out=on_node.get_meta("value%s"%(("_"+str(val)) if val>-1 else ""),0) 18 | var node=null 19 | var last_out=out 20 | var out_type=on_node.get_meta("type_%s"%str(val)) 21 | 22 | while out is String and out.contains("|"): 23 | last_out=out 24 | var split_out=out.split("|") 25 | node=on_graph.get_node(split_out[0]) 26 | var node_ref=null if not node.has_meta(&"SourceRef") else node.get_meta(&"SourceRef",null) 27 | if node_ref!=null && node_ref.Parameters[0].PartOnSide==1: 28 | out=node.get_meta(&"var_name",node.get_meta(&"type")+str(node.get_parent().get_children().find(node))) 29 | else:out=node.get_meta(split_out[1]) 30 | out_type=node.get_meta("type_"+last_out.split("|")[1].split("_")[1],TYPE_NIL) 31 | 32 | if default_value_types.has(out):return default_value_types[out] 33 | if out_type == TYPE_INT:return TYPE_FLOAT 34 | return out_type 35 | #endregion 36 | 37 | #region used when a value can be a float/vector2 input/output. used mainly by the math nodes 38 | func connect_float_can_be_vector(action,from_node,to_node,from_port,to_port,graph): 39 | var from_block = graph.get_node(String(from_node)) 40 | var to_block = graph.get_node(String(to_node)) 41 | 42 | var based_on= from_block.get_meta(&"action") == action 43 | var added_vector:bool=false 44 | if based_on: 45 | var s_port=from_block.get_output_port_slot(from_port) 46 | var val=from_block.get_meta(&"type_%s"%str(s_port));var to_slot=to_block.get_input_port_slot(to_port) 47 | to_block.set_meta(&"connected_left_%s"%str(to_slot),max(to_block.get_meta(&"connected_left_%s"%str(to_slot),0)+1,0)) 48 | from_block.set_meta(&"connected_right_%s"%str(s_port),max(from_block.get_meta(&"connected_right_%s"%str(s_port),0)+1,0)) 49 | if val==TYPE_VECTOR2:added_vector=true 50 | else: 51 | var s_port=to_block.get_input_port_slot(to_port) 52 | var val=to_block.get_meta(&"type_%s"%str(s_port));var to_slot=from_block.get_output_port_slot(from_port) 53 | from_block.set_meta(&"connected_right_%s"%str(to_slot),max(from_block.get_meta(&"connected_right_%s"%str(to_slot),0)+1,0)) 54 | to_block.set_meta(&"connected_left_%s"%str(s_port),max(to_block.get_meta(&"connected_left_%s"%str(s_port),0)+1,0)) 55 | if val==TYPE_VECTOR2:added_vector=true 56 | var change_block = from_block if based_on else to_block 57 | if added_vector or get_value_type(change_block,2) == TYPE_VECTOR2 or get_value_type(change_block,1) == TYPE_VECTOR2 or get_value_type(change_block,0) == TYPE_VECTOR2: 58 | BlockColoring.ChangePortType(change_block,0,2,TYPE_VECTOR2) 59 | BlockColoring.ChangePortType(change_block,1,1,TYPE_VECTOR2) 60 | BlockColoring.ChangePortType(change_block,2,1,TYPE_VECTOR2) 61 | else: 62 | BlockColoring.ChangePortType(change_block,0,2,TYPE_FLOAT) 63 | BlockColoring.ChangePortType(change_block,1,1,TYPE_FLOAT) 64 | BlockColoring.ChangePortType(change_block,2,1,TYPE_FLOAT) 65 | 66 | 67 | func disconnect_float_can_be_vector(action,from_node,to_node,from_port,to_port,graph): 68 | var self_node=graph.get_node(String(to_node));var node=graph.get_node(String(from_node)) 69 | var based_on=node if node.get_meta(&"action") ==action else self_node 70 | 71 | if based_on==self_node: 72 | var s_port=node.get_output_port_slot(from_port) 73 | var to_slot=based_on.get_input_port_slot(to_port) 74 | based_on.set_meta(&"connected_left_%s"%str(to_slot),max(based_on.get_meta(&"connected_left_%s"%str(to_slot),0)-1,0)) 75 | node.set_meta(&"connected_right_%s"%str(s_port),max(node.get_meta(&"connected_right_%s"%str(node.get_output_port_slot(s_port)),0)-1,0)) 76 | BlockColoring.ChangePortType(based_on,to_slot,3,TYPE_FLOAT) 77 | else: 78 | var s_port=self_node.get_input_port_slot(to_port) 79 | var to_slot=based_on.get_output_port_slot(from_port) 80 | based_on.set_meta(&"connected_right_%s"%str(to_slot),max(based_on.get_meta(&"connected_right_%s"%str(to_slot),0)-1,0)) 81 | self_node.set_meta(&"connected_left_%s"%str(s_port),max(self_node.get_meta(&"connected_left_%s"%str(s_port),0)-1,0)) 82 | BlockColoring.ChangePortType(based_on,to_slot,3,TYPE_FLOAT) 83 | for value in based_on.get_meta(&"value_count"): 84 | if based_on.get_meta(&"connected_left_%s"%str(value),0)>0 or based_on.get_meta(&"connected_right_%s"%str(value),0)>0:continue 85 | BlockColoring.ChangePortType(based_on,value,3,TYPE_FLOAT) 86 | 87 | if get_value_type(based_on,2) == TYPE_VECTOR2 or get_value_type(based_on,1) == TYPE_VECTOR2 or get_value_type(based_on,0) == TYPE_VECTOR2:BlockColoring.ChangePortType(based_on,0,2,TYPE_VECTOR2);BlockColoring.ChangePortType(based_on,1,1,TYPE_VECTOR2);BlockColoring.ChangePortType(based_on,2,1,TYPE_VECTOR2) 88 | else:BlockColoring.ChangePortType(based_on,0,2,TYPE_FLOAT);BlockColoring.ChangePortType(based_on,1,1,TYPE_FLOAT);BlockColoring.ChangePortType(based_on,2,1,TYPE_FLOAT) 89 | 90 | #endregion 91 | 92 | 93 | 94 | 95 | 96 | #func DecomposeVector_connected(self_node,from_node,from_port,to_port,graph): 97 | #var node=graph.get_node(String(from_node)) 98 | #self_node=graph.get_node(String(self_node)) 99 | # 100 | #var use_node=node if node.get_meta(&"action")=="DecomposeVector" else self_node 101 | #if use_node!=node:return 102 | # 103 | #var port=self_node.get_output_port_slot(from_port) 104 | #var val=self_node.get_meta(&"value_%s"%(str(port))) 105 | # 106 | #if val==null:return 107 | #node.set_meta(&"value_1",val+".x") 108 | #node.set_meta(&"value_2",val+".y") 109 | 110 | 111 | func Float_connected(self_node,from_node,from_port,to_port,graph): 112 | var node=graph.get_node(String(from_node)) 113 | var port=node.get_output_port_slot(from_port) 114 | var val=node.get_meta(&"value_%s"%(str(port) if not node.get_meta(&"type").contains("variable") else "0")) 115 | if val==null:return 116 | if self_node is String or self_node is StringName:self_node=graph.get_node(String(self_node)) 117 | self_node.set_meta(&"value_1",val) 118 | 119 | 120 | 121 | #region math functions 122 | func add_connected(from_node,to_node,from_port,to_port,graph): 123 | connect_float_can_be_vector("Add",from_node,to_node,from_port,to_port,graph) 124 | 125 | func add_disconnected(from_node,to_node,from_port,to_port,graph): 126 | disconnect_float_can_be_vector("Add",from_node,to_node,from_port,to_port,graph) 127 | 128 | func sub_connected(from_node,to_node,from_port,to_port,graph): 129 | connect_float_can_be_vector("Sub",from_node,to_node,from_port,to_port,graph) 130 | 131 | func sub_disconnected(from_node,to_node,from_port,to_port,graph): 132 | disconnect_float_can_be_vector("Sub",from_node,to_node,from_port,to_port,graph) 133 | 134 | func mul_connected(from_node,to_node,from_port,to_port,graph): 135 | connect_float_can_be_vector("Mul",from_node,to_node,from_port,to_port,graph) 136 | 137 | func mul_disconnected(from_node,to_node,from_port,to_port,graph): 138 | disconnect_float_can_be_vector("Mul",from_node,to_node,from_port,to_port,graph) 139 | 140 | func div_connected(from_node,to_node,from_port,to_port,graph): 141 | connect_float_can_be_vector("Div",from_node,to_node,from_port,to_port,graph) 142 | 143 | func div_disconnected(from_node,to_node,from_port,to_port,graph): 144 | disconnect_float_can_be_vector("Div",from_node,to_node,from_port,to_port,graph) 145 | 146 | func abs_connected(from_node,to_node,from_port,to_port,graph): 147 | connect_float_can_be_vector("Abs",from_node,to_node,from_port,to_port,graph) 148 | 149 | func abs_disconnected(from_node,to_node,from_port,to_port,graph): 150 | disconnect_float_can_be_vector("Abs",from_node,to_node,from_port,to_port,graph) 151 | 152 | func floor_connected(from_node,to_node,from_port,to_port,graph): 153 | connect_float_can_be_vector("Floor",from_node,to_node,from_port,to_port,graph) 154 | 155 | func floor_disconnected(from_node,to_node,from_port,to_port,graph): 156 | disconnect_float_can_be_vector("Floor",from_node,to_node,from_port,to_port,graph) 157 | 158 | func ceil_connected(from_node,to_node,from_port,to_port,graph): 159 | connect_float_can_be_vector("Ceil",from_node,to_node,from_port,to_port,graph) 160 | 161 | func ceil_disconnected(from_node,to_node,from_port,to_port,graph): 162 | disconnect_float_can_be_vector("Ceil",from_node,to_node,from_port,to_port,graph) 163 | 164 | #endregion 165 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/block/block_funcs.gd.uid: -------------------------------------------------------------------------------- 1 | uid://cy85c71krs045 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/block/block_script.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends GraphNode 3 | class_name FACSGraphNode 4 | 5 | signal disconnected_port(port:int,node:Object) 6 | 7 | func _ready(): 8 | tooltip_text=get_meta(&"action","NO_ACTION")+str(get_parent().get_children().find(self)) 9 | 10 | 11 | func get_json()->Dictionary: 12 | var json_out={ 13 | "name":name, 14 | "action":get_meta(&"action",""), 15 | "parameters":[], 16 | "position":position_offset 17 | } 18 | var i=0; 19 | while has_meta("value_%s"%str(i)): 20 | var meta=get_meta("value_%s"%str(i),null) 21 | json_out.parameters.push_back({ 22 | "value":meta, 23 | "type":get_meta("type_%s"%str(i),0) 24 | }) 25 | i+=1 26 | return json_out 27 | 28 | func load_from_json(json:Dictionary)->void: 29 | print(json) 30 | 31 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/block/block_script.gd.uid: -------------------------------------------------------------------------------- 1 | uid://c2ihif37s2jc3 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/block/code_block_resource.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends Resource 3 | class_name CodeBlockResource 4 | 5 | @export var BlockName:String="" 6 | @export var BlockCategories:PackedStringArray=PackedStringArray([]) 7 | @export var CodeLine:String="" 8 | @export var SwappableCodeLines:Dictionary={ 9 | 10 | } 11 | @export var RunnableNode:bool=false 12 | @export var Parameters:Array[CodeBlockParameters]=[] 13 | 14 | const replace_type={ 15 | TYPE_PACKED_STRING_ARRAY:TYPE_STRING 16 | } 17 | 18 | func _init() -> void: 19 | (func(): 20 | for i in Parameters.size(): 21 | Parameters[i]=Parameters[i].duplicate(true) 22 | ).call_deferred() 23 | 24 | func build_block(): 25 | var block=FACSGraphNode.new() 26 | var current_part_index:int=0 27 | block.title=BlockName 28 | if RunnableNode: 29 | load_runnable_component(block) 30 | 31 | for part_index in Parameters.size(): 32 | var part_resource = Parameters[part_index] 33 | part_resource.get_parts_for_block(block,part_index,part_index+int(RunnableNode)) 34 | reset_value(block,part_index,RunnableNode) 35 | 36 | apply_metadata(block) 37 | #EditorInterface.get_inspector().edit(block) 38 | 39 | 40 | return block 41 | 42 | func apply_metadata(block)->void: 43 | block.set_meta(&"action",BlockName) 44 | block.set_meta(&"type",",".join(BlockCategories)) 45 | block.set_meta(&"runnable",RunnableNode) 46 | block.set_meta(&"SourceRef",self) 47 | 48 | block.set_meta("value_count",Parameters.size()) 49 | 50 | func load_runnable_component(built_block)->Control: 51 | var run_item=Label.new() 52 | run_item.text="RUN" 53 | built_block.add_child(run_item) 54 | built_block.set_slot_enabled_left(0,true) 55 | built_block.set_slot_enabled_right(0,true) 56 | built_block.set_slot_color_left(0,Color("ff7664")) 57 | built_block.set_slot_color_right(0,Color("ff7664")) 58 | return run_item 59 | 60 | 61 | func load_code_line(node_data:Dictionary,node_index:int,graph:GraphEdit)->String: 62 | var use_type = node_data.get("type_0",0) 63 | var output_line="" 64 | 65 | if SwappableCodeLines && SwappableCodeLines.has(use_type): 66 | output_line=SwappableCodeLines[use_type] 67 | else: 68 | output_line = CodeLine 69 | var final_line=parse_line( 70 | output_line,node_data,node_index,graph 71 | ) 72 | 73 | return final_line + "\n\t" 74 | 75 | func parse_line(output_line,node_data,node_index,graph): 76 | var final_line = "" 77 | var split_line = output_line.split("%") 78 | 79 | for i in range(1,split_line.size(),2): 80 | var replace_segment = split_line[i].to_lower() 81 | var tokens = replace_segment.split("_") 82 | match tokens[0]: 83 | "varname": 84 | split_line[i]=node_data.get("action")+str(node_index) 85 | "param": 86 | 87 | var param_id="value_%s"%tokens[1] 88 | var ignore_rest = false 89 | var value_out=node_data.get(param_id) 90 | var is_variable:bool=false 91 | var typed_int=int(node_data["type_%s"%tokens[1]]) 92 | var converting_from_type:int=node_data.get("type_%s"%tokens[1],-1) 93 | var attached_token = "" if tokens.size()<3 else tokens[2] 94 | 95 | while value_out is String and value_out.contains("|"): 96 | var path = value_out.split("|") 97 | var checking_node=graph.get_node(path[0]) 98 | var node_obj=null 99 | 100 | if checking_node.has_meta("SourceRef"):node_obj =checking_node.get_meta("SourceRef",null) 101 | converting_from_type=checking_node.get_meta( 102 | "type_%s"%path[1].split("_")[1] 103 | ) 104 | if checking_node.get("name").begins_with("Start"): 105 | value_out = checking_node.get_meta(path[1],null) 106 | 107 | ignore_rest = true 108 | is_variable = true 109 | break 110 | if node_obj!= null and node_obj.Parameters[int(path[1].split("_")[1])].PartOnSide==1 and not node_obj.Parameters[int(path[1].split("_")[1])].specialDefault: 111 | value_out = node_obj.BlockName + str(checking_node.get_meta("node_index",0)) 112 | is_variable = true 113 | ignore_rest=true 114 | break 115 | else: 116 | value_out=graph.get_node(path[0]).get_meta(path[1],"") 117 | 118 | #print(value_out) 119 | #typed_int=checking_node.get_meta(path[1].replace("value","type")) 120 | if ignore_rest: 121 | var replaced=convert_value_type(value_out,typed_int,converting_from_type) 122 | value_out=replaced 123 | else: 124 | if replace_type.has(typed_int):typed_int=replace_type[typed_int] 125 | value_out=convert_value_type(value_out,typed_int,converting_from_type) 126 | value_out = str(value_out) 127 | if attached_token!=null and attached_token.begins_with(":"): 128 | value_out+="."+attached_token.trim_prefix(":") 129 | split_line[i]=value_out 130 | return ''.join(split_line) 131 | 132 | func reset_value(node:FACSGraphNode,value_id:int=-1,check_runnable:bool=false,force_typing:bool=false)->void: 133 | if value_id-int(check_runnable)<0:return 134 | var default = Parameters[value_id-int(check_runnable)].DefaultValue 135 | if default is PackedStringArray:default = default[0] 136 | var val_id=str(value_id+int(RunnableNode&&!check_runnable)) 137 | node.set_meta(&"value_%s"%val_id, 138 | default if not force_typing else type_convert(default,node.get_meta(&"type_%s"%val_id)) 139 | ) 140 | 141 | value_changed(node,value_id,check_runnable) 142 | 143 | func value_changed(node,value_id,check_runnable)->void: 144 | if node.get_parent()==null or Parameters.size()==0:return 145 | var param = Parameters[value_id] 146 | if param.extra_resets!=null:for param_id in param.extra_resets: 147 | 148 | var node_data = {} 149 | for meta_tag in node.get_meta_list(): 150 | node_data[meta_tag.to_lower()]=node.get_meta(meta_tag) 151 | var final_out=parse_line(Parameters[param_id].specialDefault,node_data,node.get_parent().get_children().find(node),node.get_parent()) 152 | 153 | node.set_meta(&"value_%s"%str(param_id+int(!check_runnable&&RunnableNode)),final_out) 154 | 155 | 156 | func convert_value_type(value_out,typed_int,initial_type): 157 | var starting_type=typeof(value_out) 158 | 159 | #print(initial_type,",",typed_int) 160 | #if initial_type==typed_int:return value_out 161 | match(typed_int): 162 | TYPE_INT: 163 | 164 | if initial_type==TYPE_VECTOR2:return "%s.x"%value_out 165 | TYPE_FLOAT: 166 | if initial_type==TYPE_VECTOR2:return value_out.x if starting_type==TYPE_VECTOR2 else value_out+".x" 167 | return value_out 168 | 169 | TYPE_VECTOR2: 170 | if initial_type==TYPE_FLOAT:return "Vector2(%s,%s)"%[str(value_out if value_out else 0),str(value_out if value_out else 0)] 171 | if starting_type==TYPE_FLOAT:return "Vector2(%s,%s)"%[str(value_out),str(value_out)] 172 | if value_out is Vector2: 173 | value_out=var_to_str(value_out) 174 | TYPE_STRING: 175 | if initial_type==TYPE_PACKED_STRING_ARRAY:return value_out 176 | return value_out 177 | 178 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/block/code_block_resource.gd.uid: -------------------------------------------------------------------------------- 1 | uid://b6n6yaklegapt 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/codehighlight.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="CodeHighlighter" format=3 uid="uid://g0qjjgb0nwf8"] 2 | 3 | [resource] 4 | number_color = Color(0.388235, 1, 0.388235, 1) 5 | symbol_color = Color(0.65, 0.760833, 1, 1) 6 | function_color = Color(0.690196, 0.788235, 1, 1) 7 | member_variable_color = Color(0.439216, 0.627451, 1, 1) 8 | keyword_colors = { 9 | "AnimatedItem": Color(0, 1, 0.7, 1), 10 | "Array": Color(0.388235, 1, 0.388235, 1), 11 | "Dictionary": Color(0.388235, 1, 0.388235, 1), 12 | "Vector2": Color(0, 1, 0.698039, 1), 13 | "container_info": Color(0.4, 1, 0.819608, 1), 14 | "float": Color(0, 1, 0.698039, 1), 15 | "func": Color(1, 0.278431, 0.278431, 1), 16 | "int": Color(0, 1, 0.698039, 1), 17 | "item_index": Color(0.4, 1, 0.819608, 1), 18 | "item_node": Color(0.4, 1, 0.819608, 1), 19 | "output_data": Color(0.4, 1, 0.819608, 1), 20 | "return": Color(1, 0.278431, 0.278431, 1), 21 | "total_items": Color(0.4, 1, 0.819608, 1), 22 | "var": Color(1, 0.278431, 0.278431, 1) 23 | } 24 | color_regions = { 25 | "' '": Color(1, 0.968627, 0.360784, 1) 26 | } 27 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/converters/json_visual_converter.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends RefCounted 3 | class_name FACSJson 4 | 5 | 6 | 7 | 8 | static func convert_tree(graph:GraphEdit)->Dictionary: 9 | var node_list=graph.get_children() 10 | node_list=node_list.filter(func(a):return not ["StartNode","StartContainerNode","_connection_layer"].has(a.name)) 11 | var converted_list=[] 12 | #var compiled_list=[] 13 | var converted_connections=[] 14 | for node in node_list: 15 | if not node is GraphNode:continue 16 | converted_list.push_back(node.get_json()) 17 | for connection in graph.connections: 18 | converted_connections.push_back( 19 | { 20 | "from":String(connection.from_node), 21 | "to":String(connection.to_node), 22 | "from_port":connection.from_port, 23 | "to_port":connection.to_port 24 | } 25 | ) 26 | 27 | #return {"nodes":converted_list,"connections":converted_connections,"compiler_data":compiled_list} 28 | return {"nodes":converted_list,"connections":converted_connections} 29 | 30 | 31 | ##fixes issues when converting between json text and godot dictionaries making vectors and other types into strings 32 | static func correct_variable_typing(value): 33 | if value is String and value.begins_with("("):value = str_to_var("Vector2"+value) 34 | return value 35 | 36 | 37 | static func convert_json(json_data,graph:GraphEdit,blockList): 38 | for node in graph.get_children(): 39 | if node.get_meta("action","").begins_with("INITIALIZE") or node.name=="_connection_layer":continue 40 | node.queue_free() 41 | graph.clear_connections() 42 | await graph.get_tree().process_frame 43 | 44 | 45 | for node_data in json_data.nodes: 46 | var node=blockList.create_item_block(node_data.name if not node_data.has("action") else node_data.action,false,graph) 47 | node.name=node_data.name 48 | node.position_offset=str_to_var("Vector2"+node_data.position) 49 | (func(): 50 | var i=0 51 | #if node_data.type==0: 52 | #node.set_meta(&"value_0",node_data["action"]) 53 | #var value=correct_variable_typing(node_data["value"]) 54 | #node.set_meta(&"value_1",value) 55 | 56 | while node_data.has("value_%s"%str(i)): 57 | var value=correct_variable_typing(node_data["value_%s"%str(i)]) 58 | if value == null: 59 | var ref = node.get_meta(&"SourceRef") 60 | if ref!=null: 61 | ref.reset_value(node,i,false,true) 62 | node.set_meta(&"value_%s"%str(i),value) 63 | i+=1 64 | ).call() 65 | graph.current_selected_nodes=[] 66 | for connection in json_data.connections: 67 | var link_nodes={ 68 | "from_node":connection.from, 69 | "to_node":connection.to, 70 | "from_port":connection.from_port, 71 | "to_port":connection.to_port 72 | } 73 | graph.call_deferred('emit_signal','connection_request',link_nodes.from_node,link_nodes.from_port,link_nodes.to_node,link_nodes.to_port) 74 | 75 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/converters/json_visual_converter.gd.uid: -------------------------------------------------------------------------------- 1 | uid://b7pgbcrn5cawb 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/converters/visual_node.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends Resource 3 | class_name visual_node 4 | 5 | var on_graph:GraphEdit 6 | enum nodeTypes{ 7 | Variable, 8 | Function, 9 | VariableFunction 10 | } 11 | 12 | var data={ 13 | 14 | } 15 | 16 | var link_node 17 | 18 | func _init(node,graph)->void: 19 | 20 | on_graph=graph 21 | link_node=node 22 | if not node.has_meta("type"): 23 | data={'type':-1} 24 | else: 25 | match node.get_meta("type"): 26 | "variable": 27 | data={ 28 | "type":nodeTypes.Variable, 29 | "name":node.get_meta(&"value_0"), 30 | "var_name":node.get_meta(&"value_0"), 31 | "var_type":node.get_meta(&"action"), 32 | "value":node.get_meta(&"value_1"), 33 | } 34 | "function": 35 | data={ 36 | "type":nodeTypes.Function, 37 | "name":node.get_meta(&"action"), 38 | } 39 | for value in node.get_meta(&"value_count"): 40 | data['value_%s'%str(value)]=node.get_meta(&"value_%s"%str(value)) 41 | "variablefunction": 42 | data={ 43 | "type":nodeTypes.VariableFunction, 44 | "name":node.get_meta(&"action"), 45 | "var_name":node.get_meta(&"action")+str(on_graph.get_children().find(node)), 46 | 'value':node.get_meta(&"action")+str(on_graph.get_children().find(node)), 47 | } 48 | for value in node.get_meta(&"value_count"): 49 | data['value_%s'%str(value)]=node.get_meta(&"value_%s"%str(value)) 50 | for type in node.get_meta_list().filter(func(v):return v.begins_with("type_")): 51 | data[type]=node.get_meta(type) 52 | 53 | 54 | func is_variable()->bool:return data.type==nodeTypes.Variable or data.type==nodeTypes.VariableFunction 55 | 56 | 57 | const default_value_types={ 58 | "item_node.rotation":TYPE_FLOAT, 59 | "item_node.position":TYPE_VECTOR2, 60 | "item_node.global_position":TYPE_VECTOR2, 61 | "item_node.scale":TYPE_VECTOR2, 62 | 63 | } 64 | 65 | func convert_value_type(value,to_type:int=TYPE_NIL,on_node:GraphNode=null): 66 | if value is int:value = float(value) 67 | var cur_type=typeof(value) 68 | if value is String and not to_type==TYPE_STRING: 69 | if default_value_types.has(String(value)): 70 | cur_type=default_value_types[value] 71 | else: 72 | if String(value).begins_with("Tween."): 73 | cur_type=TYPE_INT 74 | else: 75 | if on_node and on_node.has_meta(value): 76 | cur_type=typeof(on_node.get_meta(value)) 77 | match to_type: 78 | TYPE_FLOAT: 79 | if(cur_type==TYPE_VECTOR2): 80 | return value.x if not value is String else value+".x" 81 | TYPE_VECTOR2: 82 | if(cur_type==TYPE_FLOAT): 83 | return "Vector2(%s,%s)"%[str(value),str(value)] 84 | return value 85 | 86 | 87 | 88 | func get_value(val:int=0,val_type:int=TYPE_NIL): 89 | var out=data.get("value%s"%(("_"+str(val)) if val>-1 else "")) 90 | #loops until it hits the primary reference it is linked to 91 | var node=null 92 | while out is String and out.contains("|"): 93 | var split_out=out.split("|") 94 | node=on_graph.get_node(split_out[0]) 95 | if ["variable","variablefunction"].has(node.get_meta(&"type")): 96 | out=node.get_meta(&"var_name") 97 | else:out=node.get_meta(split_out[1]) 98 | return var_to_str(convert_value_type(out,val_type,node)).replace("\"","") 99 | 100 | 101 | func get_function_content()->String: 102 | match data.name: 103 | "INITIALIZE": 104 | return ""; 105 | "INITIALIZE_CONTAINER": 106 | return "" 107 | "Add": 108 | return "var %s = %s+%s\n\t"%[data.value,get_value(1,data['type_1']),get_value(2,data['type_2'])] 109 | "Sub": 110 | return "var %s = %s-%s\n\t"%[data.value,get_value(1,data['type_1']),get_value(2,data['type_2'])] 111 | "Mul": 112 | return "var %s = %s*%s\n\t"%[data.value,get_value(1,data['type_1']),get_value(2,data['type_2'])] 113 | "Div": 114 | return "var %s = %s/%s\n\t"%[data.value,get_value(1,data['type_1']),get_value(2,data['type_2'])] 115 | "Min": 116 | return "var %s = min(%s,%s)\n\t"%[data.value,get_value(1,TYPE_FLOAT),get_value(2,TYPE_FLOAT)] 117 | "Max": 118 | return "var %s = max(%s,%s)\n\t"%[data.value,get_value(1,TYPE_FLOAT),get_value(2,TYPE_FLOAT)] 119 | "Floor": 120 | return "var %s = %s\n\t"%[data.value,"floor(%s)"%get_value(1,data['type_1']) if data['type_1']==TYPE_FLOAT else "%s.floor()"%get_value(1,data['type_1'])] 121 | "Ceil": 122 | return "var %s = %s\n\t"%[data.value,"ceil(%s)"%get_value(1,data['type_1']) if data['type_1']==TYPE_FLOAT else "%s.ceil()"%get_value(1,data['type_1'])] 123 | "Abs": 124 | return "var %s = %s\n\t"%[data.value,"abs(%s)"%get_value(1,data['type_1']) if data['type_1']==TYPE_FLOAT else "%s.abs()"%get_value(1,data['type_1'])] 125 | "Rotate": 126 | return "var %s = %s.rotated(%s)\n\t"%[data.value,get_value(1,TYPE_VECTOR2),get_value(2,TYPE_FLOAT)] 127 | "DecomposeVector": 128 | return "" 129 | "ComposeVector": 130 | return "var %s = Vector2(%s,%s)\n\t"%[data.value,get_value(1,TYPE_FLOAT),get_value(2,TYPE_FLOAT)] 131 | "SetPosition": 132 | return "item_node.chain_action(0,%s,%s,%s,%s) #Position\n\t"%[get_value(0,TYPE_VECTOR2),get_value(1,TYPE_FLOAT),get_value(2,TYPE_INT),get_value(3,TYPE_BOOL)] 133 | "SetRotation": 134 | return "item_node.chain_action(1,%s,%s,%s) #Rotation\n\t"%[get_value(0,TYPE_FLOAT),get_value(1,TYPE_FLOAT),get_value(2,TYPE_INT)] 135 | "SetScale": 136 | return "item_node.chain_action(2,%s,%s,%s) #Scale\n\t"%[get_value(0,TYPE_VECTOR2),get_value(1,TYPE_FLOAT),get_value(2,TYPE_INT)] 137 | "SyncParameters": 138 | return "item_node.sync_chains()\n\t" 139 | #return "output_data.Positions.push_back({'tween_type':-9});output_data.Rotations.push_back({'tween_type':-9});output_data.Scales.push_back({'tween_type':-9})\n\t" 140 | "RandomFloat": 141 | return "var %s = randf_range(%s,%s)\n\t"%[data.value,get_value(1,TYPE_FLOAT),get_value(2,TYPE_FLOAT)] 142 | "RandomVector2": 143 | return "var %s = Vector2(randf_range(%s,%s),randf_range(%s,%s))\n\t"%[data.value,get_value(1,TYPE_FLOAT),get_value(3,TYPE_FLOAT),get_value(2,TYPE_FLOAT),get_value(4,TYPE_FLOAT)] 144 | "ExternalFloat": 145 | return "var %s = _external_variables[%s]\n\t"%[data.value,data.get("value_1","invalid")] 146 | "Sin": 147 | return "var %s = sin(%s)\n\t"%[data.value,get_value(1,TYPE_FLOAT)] 148 | "Cos": 149 | return "var %s = cos(%s)\n\t"%[data.value,get_value(1,TYPE_FLOAT)] 150 | "Tan": 151 | return "var %s = tan(%s)\n\t"%[data.value,get_value(1,TYPE_FLOAT)] 152 | return "" 153 | 154 | func get_content()->String: 155 | if not data.has("type"):return "" 156 | match data.type: 157 | nodeTypes.Variable: 158 | return "var %s:%s=%s\n\t"%[data.name,data.var_type.to_lower().capitalize().replace(" ",""),get_value(-1)] 159 | nodeTypes.Function: 160 | return get_function_content() 161 | nodeTypes.VariableFunction: 162 | return get_function_content() 163 | return "" 164 | 165 | ##gets the json that is used to rebuild a node structure when loading from the json 166 | func get_json(): 167 | var out=data.duplicate() 168 | 169 | out.position=link_node.position_offset 170 | return out 171 | 172 | ##compiles the value data directly to what it needs for use when compiling 173 | func get_compile_format_json(graph_node:GraphEdit): 174 | var out={} 175 | var used_keys=data.keys().filter(func(v):return v.begins_with("value_")) 176 | for key in used_keys: 177 | var key_val=data[key] 178 | while key_val is String and key_val.contains("|"): 179 | key_val=graph_node.get_node(key_val.split("|")[0]).get_meta(key_val.split("|")[1]) 180 | out[key]=key_val 181 | return out 182 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/converters/visual_node.gd.uid: -------------------------------------------------------------------------------- 1 | uid://bpgp7jeujcray 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/converters/visual_script_converter.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends RefCounted 3 | class_name FACSVISCompiler 4 | 5 | 6 | 7 | static func convert_node(node:GraphNode,graph:GraphEdit): 8 | if node.has_meta("ignore_in_compile"): return [] 9 | var chain=[] 10 | var connections=graph.get_connection_list().filter(func(v): 11 | return v.to_node==node.name) 12 | 13 | for connection in connections: 14 | chain.append_array(convert_node(graph.get_node(String(connection.from_node)),graph)) 15 | chain.push_back(node.name) 16 | return chain 17 | 18 | static func convert_chain_to_code(chain:Array,graph,method_name:String=graph.get_meta(&"func_name"))->Dictionary: 19 | var code_out="func %METHOD_NAME%(item_node:AnimatedItem,item_index:float=0,total_items:float=1,container_info={},_external_variables={}):\n\t\n\t" 20 | var final_chain=[] 21 | chain.map(func(v):if !final_chain.has(v):final_chain.push_back(v)) 22 | chain=final_chain 23 | final_chain=[] 24 | var variable_list:PackedStringArray=PackedStringArray() 25 | #for node in chain: 26 | #var vis_node=visual_node.new(node,graph) 27 | #if vis_node.is_variable():variable_list.push_back(vis_node.data.var_name) 28 | # 29 | #code_out+=vis_node.get_content() 30 | var i = 0 31 | for node in chain: 32 | var node_obj = graph.get_node(String(node)) 33 | node_obj.set_meta("node_index",i) 34 | i+=1 35 | i=0 36 | for node in chain: 37 | var node_obj = graph.get_node(String(node)) 38 | var ref_resource = node_obj.get_meta("SourceRef") 39 | var node_data = read_node_data(node_obj) 40 | code_out+=ref_resource.load_code_line(node_data,i,graph) 41 | i+=1 42 | code_out+="pass\n" 43 | return {"code":code_out,"variables":variable_list} 44 | 45 | 46 | static func convert_visual(graph:GraphEdit)->Dictionary: 47 | var code_out="func unset_name(item_node:AnimatedItem,item_index:float=0,total_items:float=1,container_info={},_external_variables={}):\n\t\n\t" 48 | var connection_list:=graph.get_connection_list() 49 | var chains_to_start:Array=[] 50 | var runnable_nodes = graph.get_children().filter(func(v):return v.get_meta(&"runnable",false)) 51 | for connection in connection_list: 52 | chains_to_start.push_back(connection.to_node) 53 | var node_used=String(runnable_nodes[0].name) 54 | for node in graph.get_children(): 55 | if not node.has_meta("type"):continue 56 | match node.get_meta("type"): 57 | "variable": 58 | node.set_meta(&"var_name",node.get_meta("value_0")) 59 | "variablefunction": 60 | node.set_meta(&"var_name",node.get_meta("action")+str(graph.get_children().find(node))) 61 | 62 | while true: 63 | var used=connection_list.filter(func(v):return String(v.from_node)==node_used and graph.get_node(String(v.to_node)).get_meta(&"runnable")) 64 | if used.size()==0:break 65 | node_used=String(used[0].to_node) 66 | var node_list = convert_node(graph.get_node(node_used),graph) 67 | var i = 0 68 | for node in node_list: 69 | var node_obj = graph.get_node(String(node)) 70 | node_obj.set_meta("node_index",i) 71 | i+=1 72 | i=0 73 | for node in node_list: 74 | var node_obj = graph.get_node(String(node)) 75 | var ref_resource = node_obj.get_meta("SourceRef") 76 | var node_data = read_node_data(node_obj) 77 | code_out+=ref_resource.load_code_line(node_data,i,graph) 78 | i+=1 79 | code_out+="pass;\n" 80 | 81 | return {"code":code_out,"variables":[]} 82 | 83 | #return output 84 | 85 | 86 | static func read_node_data(node:Control)->Dictionary: 87 | var output_data = {} 88 | for meta_tag in node.get_meta_list(): 89 | output_data[meta_tag.to_lower()]=node.get_meta(meta_tag) 90 | 91 | return output_data 92 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/converters/visual_script_converter.gd.uid: -------------------------------------------------------------------------------- 1 | uid://b543gn6rm0r52 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/example_animation_chains/test_chain.json: -------------------------------------------------------------------------------- 1 | {"connections":[{"from":0,"from_port":0,"to":2,"to_port":0}],"nodes":[{"name":"SetTarget","position":"(340, 20)","type":1,"value_0":"StartContainerNode|value_0","value_1":0,"value_2":0}]} -------------------------------------------------------------------------------- /addons/FancyControls/GUI/scene/2d.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RogerRandomDev/FancyControls/0857c63136dafbd05c85d05faeb2e75fd8885a74/addons/FancyControls/GUI/scene/2d.res -------------------------------------------------------------------------------- /addons/FancyControls/GUI/scene/ClassList.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/scene/ClassList.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://crddlvxtjq48j" 6 | path="res://.godot/imported/ClassList.svg-84ada8edd6f88b3a7b8f823d9ca41a1c.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/FancyControls/GUI/scene/ClassList.svg" 14 | dest_files=["res://.godot/imported/ClassList.svg-84ada8edd6f88b3a7b8f823d9ca41a1c.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/scene/CodeBox.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends HBoxContainer 3 | 4 | var converter=preload("res://addons/FancyControls/GUI/converters/visual_script_converter.gd").new() 5 | @onready var animations_container=$VBoxContainer/Container 6 | 7 | func reload_codeview()->void: 8 | var converted_view=converter.convert_visual($"../MainBox/BlockUI") 9 | $CodeEdit.text=converted_view.code.replace("%METHOD_NAME%",$"../MainBox/BlockUI".get_meta(&"func_name")) 10 | $CodeEdit.syntax_highlighter.clear_member_keyword_colors() 11 | for variable in converted_view.variables: 12 | $CodeEdit.syntax_highlighter.add_member_keyword_color(variable,Color("66ffd1")) 13 | 14 | var scr=GDScript.new() 15 | scr.source_code="@tool\nextends RefCounted\n"+converted_view.code.replace("%METHOD_NAME%","PLACEHOLDER_NAME") 16 | scr.reload() 17 | 18 | $VBoxContainer/Container/AnimatedRoundContainer.set_animation_group(scr) 19 | 20 | 21 | 22 | func _on_play_anim_pressed(): 23 | for container in animations_container.get_children(): 24 | if not container is AnimatedContainer:continue 25 | var is_currently_playing:bool=false 26 | for item in container.get_children(): 27 | if not item is AnimatedItem:continue 28 | item.manual_step=false 29 | if item._tween_position and item._tween_position.is_valid(): 30 | is_currently_playing=true 31 | item._tween_position.play() 32 | if item._tween_rotation and item._tween_rotation.is_valid(): 33 | is_currently_playing=true 34 | item._tween_rotation.play() 35 | if item._tween_scale and item._tween_scale.is_valid(): 36 | is_currently_playing=true 37 | item._tween_scale.play() 38 | if not is_currently_playing: 39 | container._editor_fit_contents() 40 | container.play_animation(container.get_animation_list()[0]) 41 | 42 | func _on_pause_anim_pressed(): 43 | for container in animations_container.get_children(): 44 | if not container is AnimatedContainer:continue 45 | for item in container.get_children(): 46 | if not item is AnimatedItem:continue 47 | item.manual_step=true 48 | if item._tween_position and item._tween_position.is_valid():item._tween_position.pause() 49 | if item._tween_rotation and item._tween_rotation.is_valid():item._tween_rotation.pause() 50 | if item._tween_scale and item._tween_scale.is_valid():item._tween_scale.pause() 51 | 52 | 53 | func _on_step_anim_pressed(): 54 | #so if you step it also pauses it for you 55 | _on_pause_anim_pressed() 56 | #step is currently hard set at 0.05 seconds 57 | #i'll add an input to change that value later 58 | 59 | #temp way to increase speed. press shift for x4 step rate 60 | var step_rate = 1+3*int(Input.is_key_pressed(KEY_SHIFT)) 61 | 62 | for container in animations_container.get_children(): 63 | if not container is AnimatedContainer:continue 64 | var is_currently_playing:bool=false 65 | for item in container.get_children(): 66 | if not item is AnimatedItem:continue 67 | if item._tween_position and item._tween_position.is_valid(): 68 | is_currently_playing=true 69 | item._tween_position.custom_step(0.05*step_rate) 70 | if item._tween_rotation and item._tween_rotation.is_valid(): 71 | is_currently_playing=true 72 | item._tween_rotation.custom_step(0.05*step_rate) 73 | if item._tween_scale and item._tween_scale.is_valid(): 74 | is_currently_playing=true 75 | item._tween_scale.custom_step(0.05*step_rate) 76 | #also done here so you can step and loop it 77 | if not is_currently_playing: 78 | container._editor_fit_contents() 79 | container.play_animation.call_deferred(container.get_animation_list()[0]) 80 | 81 | 82 | 83 | func _on_reset_anim_pressed(): 84 | get_parent().get_parent().reset_editor_container_previews() 85 | for container in animations_container.get_children(): 86 | if not container is AnimatedContainer:continue 87 | container.clear_animations() 88 | container.play_animation.call_deferred("PLACEHOLDER_NAME") 89 | 90 | 91 | func _on_option_button_item_selected(index): 92 | var new_container:AnimatedContainer 93 | match index: 94 | 0: 95 | new_container=AnimatedRoundContainer.new() 96 | new_container.border_padding=Vector2(32,32) 97 | new_container.custom_minimum_size=Vector2(256,256) 98 | new_container.size_flags_vertical=Control.SIZE_SHRINK_CENTER 99 | new_container.size_flags_horizontal=Control.SIZE_SHRINK_CENTER 100 | 1: 101 | new_container=AnimatedBoxContainer.new() 102 | new_container.box_direction=1 103 | new_container.size_flags_horizontal=Control.SIZE_EXPAND_FILL 104 | new_container.size_flags_vertical=Control.SIZE_SHRINK_CENTER 105 | new_container.custom_minimum_size=Vector2.ONE 106 | 2: 107 | new_container=AnimatedBoxContainer.new() 108 | new_container.box_direction=0 109 | new_container.size_flags_vertical=Control.SIZE_EXPAND_FILL 110 | new_container.size_flags_horizontal=Control.SIZE_SHRINK_CENTER 111 | new_container.custom_minimum_size=Vector2.ONE 112 | for i in 8: 113 | var item=Panel.new() 114 | item.custom_minimum_size=Vector2(40,40) 115 | item.size=Vector2(40,40) 116 | var item_holder=FancyAnimatedItem.new(new_container,item) 117 | new_container.add_child(item_holder) 118 | 119 | new_container.animations=$VBoxContainer/Container/AnimatedRoundContainer.animations 120 | 121 | $VBoxContainer/Container/AnimatedRoundContainer.free() 122 | $VBoxContainer/Container.add_child(new_container) 123 | new_container.name="AnimatedRoundContainer" 124 | await get_tree().process_frame 125 | await get_tree().process_frame 126 | new_container._editor_fit_contents() 127 | new_container._update_start_positions(false) 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/scene/CodeBox.gd.uid: -------------------------------------------------------------------------------- 1 | uid://bj73su5l5ruh0 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/scene/GraphNode.gd: -------------------------------------------------------------------------------- 1 | extends GraphNode 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/scene/GraphNode.gd.uid: -------------------------------------------------------------------------------- 1 | uid://cydghy62as4fx 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/scene/GroupsBox.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends VBoxContainer 3 | @onready var group_tree:Tree=$Tree 4 | 5 | @onready var manager=load("res://FACS/FACSManager.res") 6 | 7 | var base_graph 8 | 9 | func _ready(): 10 | 11 | ($"../../ChainChooseForGroup" as FileDialog).current_dir="res://FACS/Editor" 12 | group_tree.set_column_title(0,"Name") 13 | group_tree.set_column_title(1,"Method(Optional)") 14 | group_tree.set_column_title(2,"File Path") 15 | group_tree.set_column_title(3,"Compile") 16 | group_tree.set_column_expand_ratio(0,4.0) 17 | group_tree.set_column_expand_ratio(1,1.0) 18 | group_tree.set_column_expand_ratio(2,3.0) 19 | group_tree.set_column_expand_ratio(3,0.0) 20 | group_tree.set_column_expand(3,false) 21 | var root=group_tree.create_item() 22 | 23 | manager.load_from_data() 24 | 25 | load_from_manager.call_deferred() 26 | 27 | (func(): 28 | base_graph=$"../MainBox/BlockUI".duplicate(DUPLICATE_GROUPS|DUPLICATE_SCRIPTS|DUPLICATE_SIGNALS|DUPLICATE_USE_INSTANTIATION) 29 | 30 | ).call() 31 | 32 | func load_from_manager()->void: 33 | group_tree.clear() 34 | group_tree.create_item() 35 | var group_list=manager.get_group_list() 36 | var root_item=group_tree.get_root() 37 | var n=0 38 | for group_name in group_list: 39 | var group_item=root_item.create_child() 40 | group_item.set_text(0,group_name) 41 | group_item.set_text_alignment(3,HORIZONTAL_ALIGNMENT_CENTER) 42 | group_item.set_meta(&"is_group",true) 43 | group_item.set_meta(&"group_name",group_name) 44 | 45 | var group_binds=manager.get_chains_in_group(group_name) 46 | var invalid_bindings=manager.get_invalid_bindings_in_group(group_name) 47 | for bind in group_binds: 48 | var bound_item:TreeItem=group_item.create_child() 49 | #so i can keep track of things in the item itself 50 | bound_item.set_meta(&"group_name",group_name) 51 | bound_item.set_meta(&"is_group",false) 52 | bound_item.set_meta(&"name",bind.binding_name) 53 | bound_item.add_button(3,load("res://addons/FancyControls/GUI/scene/Remove.svg"),2) 54 | bind.insert_data_in_treeitem(bound_item) 55 | 56 | #if invalid_bindings.find(true)<0: 57 | group_item.add_button(3,load("res://addons/FancyControls/GUI/Add.svg"),0,false,"Add Chain To Group") 58 | group_item.add_button(3,load("res://addons/FancyControls/GUI/AssetLib.svg"),1,false,"Compile Group") 59 | 60 | 61 | 62 | func _on_tree_item_collapsed(item:TreeItem): 63 | var sub_items:int=item.get_child_count() 64 | 65 | item.set_text(3,"") 66 | item.set_custom_color(3,Color.WHITE) 67 | if not item.collapsed:return 68 | 69 | #does this to make sure you always know something is invalid in a given group 70 | for child in sub_items: 71 | if item.get_child(child).get_text(3)=="!": 72 | item.set_text(3,"!") 73 | item.set_custom_color(3,Color.RED) 74 | break 75 | 76 | 77 | var prev_selected:TreeItem=null 78 | #i use this so you have to double-click it to make it editable 79 | func _on_tree_item_selected(): 80 | var selected_column=group_tree.get_selected_column() 81 | 82 | if prev_selected!=null and not prev_selected==group_tree.get_selected(): 83 | prev_selected.set_editable(0,false) 84 | #prev_selected.set_editable(1,false) 85 | prev_selected.set_editable(2,false) 86 | prev_selected=group_tree.get_selected() 87 | 88 | #path or name of a group function 89 | if [0,1].has(selected_column) and not (selected_column>0 and group_tree.get_selected().get_parent()==group_tree.get_root()): 90 | group_tree.get_selected().set_editable(selected_column,true) 91 | 92 | ##when pressed it should attempt to compile the group into a script file of the functions 93 | func _on_tree1_button_clicked(item, column, id, mouse_button_index): 94 | pass # Replace with function body. 95 | 96 | 97 | func _on_tree_item_edited(): 98 | var group_changing:bool=prev_selected.get_meta(&"is_group") 99 | #when you are changing the name of a group itself 100 | if group_changing: 101 | var old_name=prev_selected.get_meta(&"group_name") 102 | var name_changed_successfully:bool=manager.change_group_name(old_name,prev_selected.get_text(0)) 103 | if not name_changed_successfully: 104 | prev_selected.set_text(0,old_name) 105 | else: 106 | prev_selected.set_meta(&"group_name",prev_selected.get_text(0)) 107 | for child in prev_selected.get_children(): 108 | child.set_meta(&"group_name",prev_selected.get_text(0)) 109 | 110 | else: 111 | if prev_selected.get_cell_mode(1)==TreeItem.CELL_MODE_RANGE: 112 | var changed_script_method=manager.change_group_binding_script_method(prev_selected.get_meta(&"group_name"),prev_selected.get_meta(&"linked_resource"),prev_selected.get_text(1).split(",")[prev_selected.get_range(1)]) 113 | #now when you are changing an items contents within the groupings 114 | var name_changed_successfully:bool=manager.change_group_binding_name(prev_selected.get_meta(&"group_name"),prev_selected.get_meta(&"linked_resource"),prev_selected.get_text(0)) 115 | if not name_changed_successfully: 116 | prev_selected.set_text(0,prev_selected.get_meta(&"name")) 117 | else:prev_selected.set_meta(&"name",prev_selected.get_text(0)) 118 | func _on_tree_item_activated(): 119 | #checks when something is double-clicked 120 | #row 2 is for items that are paths. 121 | #it should pull out a dialog to select a file to use instead 122 | if group_tree.get_selected_column()==2 and not prev_selected.get_meta(&"is_group"): 123 | $"../../ChainChooseDialog".visible=true 124 | 125 | 126 | 127 | func _on_chain_choose_dialog_file_selected(path): 128 | var linked_res=prev_selected.get_meta(&"linked_resource") 129 | linked_res.binding_link_path=path 130 | manager.rebind_path_on(prev_selected.get_parent().get_text(0),linked_res,path) 131 | prev_selected.set_text(2,path) 132 | if linked_res.is_binding_valid(): 133 | prev_selected.set_text(3,"") 134 | prev_selected.set_custom_color(3,Color.WHITE) 135 | prev_selected.set_custom_color(2,Color.WHITE) 136 | if path.ends_with(".gd"): 137 | #why do they not document that you can do this? 138 | prev_selected.set_cell_mode(1,TreeItem.CELL_MODE_RANGE) 139 | var end_of_function_regex=RegEx.create_from_string("\\nfunc [0-z]+") 140 | var loading_script_contents=FileAccess.get_file_as_string(path) 141 | var outputs=end_of_function_regex.search_all(loading_script_contents) 142 | prev_selected.set_text(1, 143 | ",".join(Array(outputs).map(func(v):return v.strings[0].trim_prefix("\nfunc "))) 144 | ) 145 | else: 146 | prev_selected.set_cell_mode(1,TreeItem.CELL_MODE_STRING) 147 | 148 | 149 | 150 | func _on_create_group_button_pressed(): 151 | var n=0 152 | while not manager.create_group("group%s"%str(n)):n+=1 153 | load_from_manager() 154 | 155 | 156 | func _on_remove_group_button_pressed(): 157 | if group_tree.get_selected()==null or not group_tree.get_selected().get_parent()==group_tree.get_root():return 158 | manager.remove_group(group_tree.get_selected().get_text(0)) 159 | load_from_manager() 160 | 161 | 162 | 163 | func _on_tree_button_clicked(item, column, id, mouse_button_index): 164 | match id: 165 | 0: 166 | group_tree.set_selected(item,3) 167 | $"../../ChainChooseForGroup".visible=true 168 | pass 169 | 1: 170 | #compile grouping 171 | #FACSGroupCompiler.compile_group(item,base_graph,$"../MainBox/VBoxContainer/BlockList") 172 | FACSGroupCompiler.compile_group(item,base_graph,$"../MainBox/VBoxContainer/BlockList") 173 | 2: 174 | #remove item button 175 | group_tree.set_selected(item,3) 176 | $"../../ConfirmationDialog2".visible=true 177 | 178 | func _on_chain_choose_for_group_file_selected(path): 179 | var group_name=prev_selected.get_meta(&"group_name") 180 | var path_split=path.split("/") 181 | var bind_name=path_split[len(path_split)-1].split(".")[0] 182 | 183 | if not manager.check_facs_group_can_add(group_name,bind_name,path):return 184 | manager.bind_facs_to_group( 185 | group_name, 186 | bind_name, 187 | path 188 | ) 189 | load_from_manager() 190 | 191 | 192 | 193 | func _on_confirmation_remove_group_func_confirmed(): 194 | manager.remove_chain_from_group(prev_selected.get_meta(&"group_name"),prev_selected.get_text(0)) 195 | prev_selected.free() 196 | 197 | 198 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/scene/GroupsBox.gd.uid: -------------------------------------------------------------------------------- 1 | uid://da2qpubt2cmkw 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/scene/Remove.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/scene/Remove.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://iu8xfkufmek8" 6 | path="res://.godot/imported/Remove.svg-45ff34020841a93912340f4d34290d82.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://addons/FancyControls/GUI/scene/Remove.svg" 14 | dest_files=["res://.godot/imported/Remove.svg-45ff34020841a93912340f4d34290d82.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/scene/UndoRedoGraphManager.gd: -------------------------------------------------------------------------------- 1 | extends UndoRedo 2 | 3 | 4 | 5 | 6 | func add_action()->void: 7 | pass 8 | 9 | func clear()->void: 10 | pass 11 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/scene/UndoRedoGraphManager.gd.uid: -------------------------------------------------------------------------------- 1 | uid://doi0v64k82fsr 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/scene/gui_root_script.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends Control 3 | 4 | @onready var json_converted=load("res://addons/FancyControls/GUI/converters/json_visual_converter.gd").new() 5 | 6 | 7 | 8 | 9 | 10 | func reset_editor_container_previews()->void: 11 | for animated_cont in $Box/CodeBox/VBoxContainer/Container.get_children(): 12 | if animated_cont is AnimatedContainer: 13 | animated_cont._editor_fit_contents() 14 | 15 | animated_cont._update_start_positions(false) 16 | animated_cont.clear_animations() 17 | 18 | 19 | 20 | 21 | func _input(event): 22 | if visible and event is InputEventKey and event.is_pressed() and event.ctrl_pressed: 23 | accept_event() 24 | if visible and event is InputEventKey: 25 | if event.keycode >= KEY_F1 and event.keycode <= KEY_F19: 26 | accept_event() 27 | if not event.is_pressed():return 28 | var tab_open=event.keycode-KEY_F1 29 | if tab_open<0 or tab_open > 2:return 30 | ($Box/TopBar/TabBar as TabBar).current_tab=tab_open 31 | 32 | 33 | 34 | 35 | func _on_tab_bar_tab_selected(tab): 36 | $Box/MainBox.visible=tab==0 37 | $Box/CodeBox.visible=tab==1 38 | $Box/GroupsBox.visible=tab==2 39 | if tab==1: 40 | reset_editor_container_previews() 41 | 42 | $Box/CodeBox.reload_codeview.call_deferred() 43 | 44 | 45 | 46 | func _on_save_button_pressed(): 47 | if $Box/TopBar/Label.text=="": 48 | $Box/TopBar/Label.grab_focus() 49 | return 50 | if FileAccess.file_exists("res://FACS/Editor/%s.FACSVis"%$Box/TopBar/Label.text): 51 | $ConfirmationDialog.visible=true 52 | 53 | return 54 | _save_confirmed() 55 | func _save_confirmed(): 56 | var converted_json=json_converted.convert_tree($Box/MainBox/BlockUI) 57 | var path_used="res://FACS/Editor/%s.FACSVis"%$Box/TopBar/Label.text 58 | var file=FileAccess.open(path_used,FileAccess.WRITE) 59 | var stored_data=JSON.stringify(converted_json).to_utf8_buffer() 60 | #i love compression 61 | var compressed_data=stored_data.compress(FileAccess.COMPRESSION_GZIP) 62 | var decompressed_size=len(stored_data) 63 | compressed_data.resize(len(compressed_data)+4) 64 | compressed_data.encode_s32(len(compressed_data)-4,decompressed_size) 65 | file.store_buffer(compressed_data) 66 | file.close() 67 | 68 | EditorInterface.get_resource_filesystem().update_file(path_used) 69 | EditorInterface.get_resource_filesystem().reimport_files(PackedStringArray([path_used])) 70 | 71 | 72 | 73 | func _on_load_button_pressed(): 74 | $ChainLoadDialog.visible=true 75 | 76 | 77 | 78 | func _on_chain_load_dialog_file_selected(path): 79 | $Box/TopBar/Label.text=Array(path.split("/")).back().trim_suffix(".FACSVis") 80 | if not FileAccess.file_exists(path):return 81 | 82 | for child in $Box/MainBox/BlockUI.get_children(): 83 | if child.name=="StartNode":continue 84 | if child.name=="StartContainerNode":continue 85 | if child.name=="_connection_layer":continue 86 | $Box/MainBox/BlockUI.remove_child(child) 87 | child.free() 88 | $Box/MainBox/BlockUI.clear_connections() 89 | var file=FileAccess.open(path,FileAccess.READ) 90 | #decompress the file, the last 4 bytes are listing how big it should be after decompression 91 | var buffer=file.get_buffer(file.get_length()) 92 | var buffer_size=buffer.decode_s32(len(buffer)-4) 93 | buffer.resize(len(buffer)-4) 94 | buffer=buffer.decompress(buffer_size,FileAccess.COMPRESSION_GZIP) 95 | var file_text=buffer.get_string_from_utf8() 96 | 97 | json_converted.convert_json( 98 | JSON.parse_string(file_text), 99 | $Box/MainBox/BlockUI, 100 | $Box/MainBox/VBoxContainer/BlockList 101 | ) 102 | file.close() 103 | 104 | if $Box/TopBar/TabBar.current_tab==1: 105 | reset_editor_container_previews() 106 | 107 | $Box/CodeBox.reload_codeview.call_deferred() 108 | $Box/MainBox/BlockUI.undo.clear_history.call_deferred() 109 | 110 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/scene/gui_root_script.gd.uid: -------------------------------------------------------------------------------- 1 | uid://daeebx5wiamen 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/scene/right_click_menu.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends PanelContainer 3 | 4 | 5 | func _ready() -> void: 6 | $VBoxContainer/NewNodeSearch.text_changed.connect(func(new_text): 7 | $VBoxContainer/NewNodeList.clear() 8 | new_text = new_text.to_lower() 9 | %BlockList.blocks.map(func(v): 10 | if new_text != "" and not v.BlockName.to_lower().contains(new_text):return 11 | $VBoxContainer/NewNodeList.add_item(v.BlockName) 12 | ) 13 | ) 14 | $VBoxContainer/NewNodeSearch.text_changed.emit("") 15 | $VBoxContainer/NewNodeList.item_activated.connect(func(index): 16 | visible=false 17 | var item_text = $VBoxContainer/NewNodeList.get_item_text(index) 18 | var block_made = %BlockList.create_item_block(item_text,false) 19 | block_made.position_offset=global_position+$"../Box/MainBox/BlockUI".scroll_offset-$"../Box/MainBox/BlockUI".global_position 20 | ) 21 | $"../Box/MainBox/BlockUI".gui_input.connect(input_on_grid) 22 | 23 | func _input(event: InputEvent) -> void: 24 | var menu_rect=get_rect() 25 | menu_rect.position=global_position 26 | if ( 27 | event is InputEventKey and event.key_label == KEY_ESCAPE or 28 | event is InputEventMouseButton and not menu_rect.has_point(event.global_position) and event.is_pressed() 29 | ): 30 | visible=false 31 | return 32 | 33 | func input_on_grid(event: InputEvent) -> void: 34 | if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_RIGHT and event.is_pressed(): 35 | if visible: 36 | visible=false 37 | return 38 | visible=true 39 | global_position=event.global_position 40 | $VBoxContainer/NewNodeSearch.clear() 41 | $VBoxContainer/NewNodeSearch.edit() 42 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/scene/right_click_menu.gd.uid: -------------------------------------------------------------------------------- 1 | uid://4m8p4m5lxv4t 2 | -------------------------------------------------------------------------------- /addons/FancyControls/GUI/scene/script.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RogerRandomDev/FancyControls/0857c63136dafbd05c85d05faeb2e75fd8885a74/addons/FancyControls/GUI/scene/script.res -------------------------------------------------------------------------------- /addons/FancyControls/Importers/FACSGroupCompiler.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends RefCounted 3 | class_name FACSGroupCompiler 4 | 5 | 6 | 7 | 8 | 9 | static func _get_method_file_as_json(path): 10 | var file=FileAccess.open(path,FileAccess.READ) 11 | #decompress the file, the last 4 bytes are listing how big it should be after decompression 12 | var buffer=file.get_buffer(file.get_length()) 13 | var buffer_size=buffer.decode_s32(len(buffer)-4) 14 | buffer.resize(len(buffer)-4) 15 | buffer=buffer.decompress(buffer_size,FileAccess.COMPRESSION_GZIP) 16 | var file_text=buffer.get_string_from_utf8() 17 | 18 | file.close() 19 | return JSON.parse_string(file_text) 20 | 21 | 22 | static func compile_group(group_root:TreeItem,graph_base:GraphEdit,blocklist)->void: 23 | var script_contents="@tool\nextends RefCounted\n#WARNING\n#ANY CHANGES MADE TO FUNCTIONS BEING RE-COMPILED WILL BE OVERWRITTEN\n\n" 24 | 25 | var end_of_function_regex=RegEx.create_from_string("\\nfunc [0-z]+") 26 | var end_of=RegEx.create_from_string("\\n[^\\t]+") 27 | 28 | for method_item in group_root.get_children(): 29 | var file_path=method_item.get_text(2) 30 | #facsvis custom files 31 | if file_path.to_upper().ends_with("FACSVIS"): 32 | var temp_graph=graph_base.duplicate(Node.DUPLICATE_SCRIPTS|Node.DUPLICATE_SIGNALS|Node.DUPLICATE_USE_INSTANTIATION) 33 | var from_file=_get_method_file_as_json(file_path) 34 | FACSJson.convert_json(from_file,temp_graph,blocklist) 35 | await blocklist.get_tree().process_frame 36 | var compiled_vis_data=FACSVISCompiler.convert_visual(temp_graph) 37 | script_contents+=compiled_vis_data.code.replace("%METHOD_NAME%",method_item.get_text(0))+"\n\n\n" 38 | else: 39 | #normal gdscript function being used instead 40 | var loading_script_contents=FileAccess.get_file_as_string(file_path) 41 | var outputs=end_of_function_regex.search_all(loading_script_contents) 42 | var my_methods=method_item.get_text(1).split(",") 43 | for output in outputs: 44 | #chops the script to pull out only the wanted function code as text to use 45 | if output.strings[0].trim_prefix("\nfunc ")!=my_methods[method_item.get_range(1)]:continue 46 | var start_at=loading_script_contents.find(output.strings[0]) 47 | var string_for=loading_script_contents.right(-start_at) 48 | var end_of_search=end_of.search_all(string_for) 49 | if len(end_of_search)>1: 50 | var end_at=string_for.find(end_of_search[1].strings[0]) 51 | string_for=string_for.left(end_at) 52 | #to replace with the chosen name to use for this method 53 | string_for=string_for.replace(output.strings[0],"func %s"%method_item.get_text(0)) 54 | script_contents+=string_for+"\n\n\n" 55 | var group_name=group_root.get_text(0) 56 | 57 | var compiled_group=GDScript.new() 58 | compiled_group.source_code=script_contents 59 | 60 | var path_used="res://FACS/Compiled/%s.gd"%group_name 61 | 62 | if FileAccess.file_exists(path_used):DirAccess.remove_absolute(ProjectSettings.globalize_path(path_used)) 63 | 64 | ResourceSaver.save(compiled_group,path_used) 65 | 66 | #force update the editor for them 67 | #var script_editor=EditorInterface.get_script_editor() 68 | EditorInterface.get_resource_filesystem().update_file(path_used) 69 | 70 | static func check_for(node): 71 | if node is ItemList:return node 72 | for child in node.get_children(true): 73 | var val=check_for(child) 74 | if val:return val 75 | 76 | -------------------------------------------------------------------------------- /addons/FancyControls/Importers/FACSGroupCompiler.gd.uid: -------------------------------------------------------------------------------- 1 | uid://b2cygxx5jujid 2 | -------------------------------------------------------------------------------- /addons/FancyControls/Importers/FACSVisGroup.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends Resource 3 | class_name FACSVisGroup 4 | 5 | 6 | @export var binary_data:PackedByteArray 7 | -------------------------------------------------------------------------------- /addons/FancyControls/Importers/FACSVisGroup.gd.uid: -------------------------------------------------------------------------------- 1 | uid://dk7wvs5morx6k 2 | -------------------------------------------------------------------------------- /addons/FancyControls/Importers/FACSVisImporter.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends EditorImportPlugin 3 | 4 | 5 | func _get_importer_name(): 6 | return "FACS.Visual" 7 | 8 | func _get_visible_name(): 9 | return "FACS Visual Animation" 10 | 11 | func _get_recognized_extensions(): 12 | return ["facsvis"] 13 | 14 | func _get_save_extension(): 15 | return "res" 16 | 17 | func _get_resource_type(): 18 | return "Resource" 19 | 20 | func _get_preset_count(): 21 | return 1 22 | 23 | func _get_priority():return 1 24 | func _get_import_order():return 1 25 | 26 | func _get_preset_name(preset_index): 27 | return "Default" 28 | 29 | func _get_import_options(path, preset_index): 30 | return [] 31 | 32 | func _get_option_visibility(path, option_name, options): 33 | return true 34 | 35 | func _import(source_file, save_path, options, r_platform_variants, r_gen_files): 36 | var file = FileAccess.open(source_file, FileAccess.READ) 37 | if file == null: 38 | return FileAccess.get_open_error() 39 | var resource=FACSVis.new() 40 | resource.binary_data=file.get_buffer(file.get_length()) 41 | 42 | return ResourceSaver.save(resource,"%s.%s"%[save_path,_get_save_extension()]) 43 | 44 | 45 | -------------------------------------------------------------------------------- /addons/FancyControls/Importers/FACSVisImporter.gd.uid: -------------------------------------------------------------------------------- 1 | uid://cq4hpbktamanf 2 | -------------------------------------------------------------------------------- /addons/FancyControls/Importers/FACSVisResource.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends Resource 3 | class_name FACSVis 4 | 5 | 6 | @export var binary_data:PackedByteArray 7 | -------------------------------------------------------------------------------- /addons/FancyControls/Importers/FACSVisResource.gd.uid: -------------------------------------------------------------------------------- 1 | uid://buhqlf48kpjh6 2 | -------------------------------------------------------------------------------- /addons/FancyControls/Importers/FacsVisGroupImporter.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends EditorImportPlugin 3 | 4 | 5 | func _get_importer_name(): 6 | return "FACS.VisualGroup" 7 | 8 | func _get_visible_name(): 9 | return "FACS Visual Animation Groups" 10 | 11 | func _get_recognized_extensions(): 12 | return ["facsvisgroup","facsgroup"] 13 | 14 | func _get_save_extension(): 15 | return "res" 16 | 17 | func _get_resource_type(): 18 | return "Resource" 19 | 20 | func _get_preset_count(): 21 | return 1 22 | 23 | func _get_priority():return 1 24 | func _get_import_order():return 1 25 | 26 | func _get_preset_name(preset_index): 27 | return "Default" 28 | 29 | func _get_import_options(path, preset_index): 30 | return [] 31 | 32 | func _get_option_visibility(path, option_name, options): 33 | return true 34 | 35 | func _import(source_file, save_path, options, r_platform_variants, r_gen_files): 36 | var file = FileAccess.open(source_file, FileAccess.READ) 37 | if file == null: 38 | return FileAccess.get_open_error() 39 | var resource=FACSVisGroup.new() 40 | resource.binary_data=file.get_buffer(file.get_length()) 41 | 42 | return ResourceSaver.save(resource,"%s.%s"%[save_path,_get_save_extension()]) 43 | 44 | 45 | -------------------------------------------------------------------------------- /addons/FancyControls/Importers/FacsVisGroupImporter.gd.uid: -------------------------------------------------------------------------------- 1 | uid://b37ifvbf3ki53 2 | -------------------------------------------------------------------------------- /addons/FancyControls/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 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 | -------------------------------------------------------------------------------- /addons/FancyControls/README.md: -------------------------------------------------------------------------------- 1 | 2 | # FACS (Fancy Animated Controls System) 3 | 4 | Addon For Godot 4.X that gives you a GUI to work with to create custom Control node animations based in a custom node container and item system. it is made to be easy to learn with a lot of capabilities for how it can be used. 5 | 6 | 7 | ## Features 8 | 9 | - GUI interface for creating Animations 10 | - GUI interface for creating/updating groups of animations to compile together 11 | - High quantity of custom Container nodes 12 | - Easy to learn code-based control of the plugin features 13 | 14 | 15 | ## Usage/Examples 16 | 17 | The project contains an example folder with a simple example of the usage cases for it. 18 | More complex usages include chaining multiple animations together to create multiple path animations, or, since the code itself is called as a function, can be directly called upon items to animate them. 19 | ## Documentation 20 | 21 | ### Animation System 22 | This is the primary reason you are here, so I'll have it explained first. 23 | The Animations are compiled, if done in the gui, down to functions that call the **`chain_action`** function on the item they are currently iterating over, and the function itself is called from the container holding the item using the function name as reference. 24 | These functions contain the following data: 25 | - item_node item being iterated 26 | - current_item item node index 27 | - total_items total number of items in container 28 | - container_data data of the container itself 29 | --- 30 | #### Creating an animation script yourself 31 | If you wish to, you can create a function yourself and tell the group system to use it by giving it the file and telling it the method name to grab and use. 32 | If you intend to also create a group file yourself, they have to be **`RefCounted`** script files as that is what it uses to store the script and run them. 33 | 34 | 35 | 36 | ## Contributing 37 | 38 | Contributions are always welcome! 39 | 40 | See `contributing.md` for ways to get started. 41 | 42 | Please adhere to this project's `code of conduct`. 43 | 44 | 45 | ## License 46 | 47 | [MIT](https://choosealicense.com/licenses/mit/) 48 | -------------------------------------------------------------------------------- /addons/FancyControls/plugin.cfg: -------------------------------------------------------------------------------- 1 | [plugin] 2 | 3 | name="Fancy Animated Controls GD4.4" 4 | description="NOTICE: This version is made for Godot 4.4. The other Variant is for Godot 4.2 and 4.3. Fancy Control nodes with animation capabilities and a custom interface for creating them. they can also be created manually or from scripts you write yourself." 5 | author="RRandom" 6 | version="1.1.5" 7 | script="FancyControls.gd" 8 | -------------------------------------------------------------------------------- /icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /icon.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://c1knnf3r3eubr" 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="FancyControls" 14 | config/features=PackedStringArray("4.4", "Forward Plus") 15 | config/icon="res://icon.svg" 16 | 17 | [editor_plugins] 18 | 19 | enabled=PackedStringArray("res://addons/FancyControls/plugin.cfg") 20 | --------------------------------------------------------------------------------