Sound FX, major work on set schedule, and some new concepts for items and portraits
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#8EEF97;}
|
||||
</style>
|
||||
<g id="Layer_1_00000170236641221328944140000001063999480100881822_">
|
||||
<path class="st0" d="M11.3,2.6c-0.7-0.7-1.8-0.7-2.5,0L2.6,8.8c-0.7,0.7-0.7,1.8,0,2.5l2.1,2.1c0.7,0.7,1.8,0.7,2.5,0l6.3-6.3
|
||||
c0.7-0.7,0.7-1.8,0-2.5L11.3,2.6z M10.1,3.8l2.1,2.1l-1.3,1.3L8.8,5.1L10.1,3.8z M7.6,6.3l2.1,2.1L8.4,9.7L6.3,7.6L7.6,6.3z
|
||||
M5.1,8.8l2.1,2.1l-1.3,1.3l-2.1-2.1L5.1,8.8z"/>
|
||||
</g>
|
||||
<g id="Layer_2_00000172438228171227073010000011096948942075396741_">
|
||||
<path class="st0" d="M14.4,11.3c-0.3-0.1-0.6-0.3-0.6-0.6v-0.3l-4.5,4.5c-0.3,0.3-0.6,0.3-0.8,0.1c-0.3-0.3-0.3-0.6,0-0.9L13,9.6
|
||||
h-0.3c-0.3-0.1-0.6-0.3-0.6-0.6c0.1-0.3,0.3-0.6,0.6-0.6l1.5,0c0.1,0,0.3,0,0.4,0.1c0.1,0.1,0.1,0.1,0.1,0.1
|
||||
c0.1,0.1,0.1,0.3,0.1,0.4l0.1,1.6C15,11,14.8,11.3,14.4,11.3z"/>
|
||||
</g>
|
||||
<path class="st0" d="M1.4,4.9C1.7,5,2,5.3,2,5.5l0,0.3l4.5-4.5C6.8,1,7.1,1,7.3,1.2c0.3,0.3,0.3,0.6,0,0.9L2.8,6.6h0.3
|
||||
c0.3,0.1,0.6,0.3,0.6,0.6C3.6,7.4,3.3,7.7,3.1,7.7l-1.5,0c-0.3,0-0.3-0.1-0.5-0.1C1,7.5,1,7.5,0.9,7.4C0.9,7.4,0.8,7.2,0.8,7.1
|
||||
L0.7,5.5C0.8,5.2,1.1,4.9,1.4,4.9z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
@@ -0,0 +1,43 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://b4kg0ekxkw2lb"
|
||||
path="res://.godot/imported/reorderable_container_icon.svg-b137036dec781405c9f5977df10d510b.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/ReorderableContainer/Icon/reorderable_container_icon.svg"
|
||||
dest_files=["res://.godot/imported/reorderable_container_icon.svg-b137036dec781405c9f5977df10d510b.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
20
addons/ReorderableContainer/Icon/reorderable_hbox_icon.svg
Normal file
20
addons/ReorderableContainer/Icon/reorderable_hbox_icon.svg
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#8EEF97;}
|
||||
</style>
|
||||
<g id="Layer_1_00000170236641221328944140000001063999480100881822_">
|
||||
<path class="st0" d="M15,6.3c0-1.1-0.9-2-2-2H3c-1.1,0-2,0.9-2,2v3.4c0,1.1,0.9,2,2,2h10c1.1,0,2-0.9,2-2V6.3z M13,6.3v3.4h-2V6.3
|
||||
H13z M9,6.3v3.4H7V6.3H9z M5,6.3v3.4H3V6.3H5z"/>
|
||||
</g>
|
||||
<g id="Layer_2_00000172438228171227073010000011096948942075396741_">
|
||||
<path class="st0" d="M10.5,15.7c-0.2-0.3-0.2-0.7,0-0.9l0.2-0.2H3.5c-0.4,0-0.7-0.3-0.7-0.6c0-0.4,0.3-0.7,0.7-0.7h7.2l-0.2-0.2
|
||||
c-0.2-0.3-0.2-0.7,0-0.9c0.3-0.2,0.7-0.2,0.9,0l1.2,1.2c0.1,0.1,0.2,0.2,0.2,0.4c0,0.1,0,0.1,0,0.2c0,0.1-0.1,0.3-0.2,0.4l-1.2,1.3
|
||||
C11.2,16,10.8,16,10.5,15.7z"/>
|
||||
</g>
|
||||
<path class="st0" d="M5.2,0.3c0.2,0.3,0.2,0.7,0,0.9L5,1.4h7.2c0.4,0,0.7,0.3,0.7,0.6c0,0.4-0.3,0.7-0.7,0.7H5l0.2,0.2
|
||||
c0.2,0.3,0.2,0.7,0,0.9C4.9,4,4.5,4,4.3,3.8L3.1,2.6C2.9,2.4,2.9,2.3,2.8,2.1c0-0.1,0-0.1,0-0.2S2.9,1.6,3,1.5l1.2-1.3
|
||||
C4.5,0,4.9,0,5.2,0.3z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,43 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bc35o8q35l74"
|
||||
path="res://.godot/imported/reorderable_hbox_icon.svg-b8929c984930c1cf79a5dffb0a9bff85.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/ReorderableContainer/Icon/reorderable_hbox_icon.svg"
|
||||
dest_files=["res://.godot/imported/reorderable_hbox_icon.svg-b8929c984930c1cf79a5dffb0a9bff85.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
20
addons/ReorderableContainer/Icon/reorderable_vbox_icon.svg
Normal file
20
addons/ReorderableContainer/Icon/reorderable_vbox_icon.svg
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#8EEF97;}
|
||||
</style>
|
||||
<g id="Layer_1_00000170236641221328944140000001063999480100881822_">
|
||||
<path class="st0" d="M6.3,1c-1.1,0-2,0.9-2,2v10c0,1.1,0.9,2,2,2h3.4c1.1,0,2-0.9,2-2V3c0-1.1-0.9-2-2-2H6.3z M6.3,3h3.4v2H6.3V3z
|
||||
M6.3,7h3.4v2H6.3V7z M6.3,11h3.4v2H6.3V11z"/>
|
||||
</g>
|
||||
<g id="Layer_2_00000172438228171227073010000011096948942075396741_">
|
||||
<path class="st0" d="M15.7,5.5c-0.3,0.2-0.7,0.2-0.9,0l-0.2-0.2v7.2c0,0.4-0.3,0.7-0.6,0.7c-0.4,0-0.7-0.3-0.7-0.7V5.3l-0.2,0.2
|
||||
c-0.3,0.2-0.7,0.2-0.9,0c-0.2-0.3-0.2-0.7,0-0.9l1.2-1.2c0.1-0.1,0.2-0.2,0.4-0.2c0.1,0,0.1,0,0.2,0c0.1,0,0.3,0.1,0.4,0.2l1.3,1.2
|
||||
C16,4.8,16,5.2,15.7,5.5z"/>
|
||||
</g>
|
||||
<path class="st0" d="M0.3,10.8c0.3-0.2,0.7-0.2,0.9,0L1.4,11V3.8c0-0.4,0.3-0.7,0.6-0.7c0.4,0,0.7,0.3,0.7,0.7V11l0.2-0.2
|
||||
c0.3-0.2,0.7-0.2,0.9,0c0.2,0.3,0.2,0.7,0,0.9l-1.2,1.2c-0.2,0.2-0.3,0.2-0.5,0.3c-0.1,0-0.1,0-0.2,0S1.6,13.1,1.5,13l-1.3-1.2
|
||||
C0,11.5,0,11.1,0.3,10.8z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,43 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://c1rxcwal2patu"
|
||||
path="res://.godot/imported/reorderable_vbox_icon.svg-6c0163d38628f550aff9f4fbed5c8a1d.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/ReorderableContainer/Icon/reorderable_vbox_icon.svg"
|
||||
dest_files=["res://.godot/imported/reorderable_vbox_icon.svg-6c0163d38628f550aff9f4fbed5c8a1d.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
7
addons/ReorderableContainer/plugin.cfg
Normal file
7
addons/ReorderableContainer/plugin.cfg
Normal file
@@ -0,0 +1,7 @@
|
||||
[plugin]
|
||||
|
||||
name="ReorderableContainer"
|
||||
description="A container similar to BoxContainer but extended with drag-and-drop style reordering functionality, and auto-scroll functionality when placed under ScrollContainer."
|
||||
author="FoolLin"
|
||||
version="1.2.4"
|
||||
script="plugin.gd"
|
||||
14
addons/ReorderableContainer/plugin.gd
Normal file
14
addons/ReorderableContainer/plugin.gd
Normal file
@@ -0,0 +1,14 @@
|
||||
@tool
|
||||
extends EditorPlugin
|
||||
|
||||
|
||||
func _enter_tree():
|
||||
add_custom_type("ReorderableContainer", "Container", preload("reorderable_container.gd"), preload("Icon/reorderable_container_icon.svg"))
|
||||
add_custom_type("ReorderableVBox", "ReorderableContainer", preload("reorderable_vbox.gd"), preload("Icon/reorderable_vbox_icon.svg"))
|
||||
add_custom_type("ReorderableHBox", "ReorderableContainer", preload("reorderable_hbox.gd"), preload("Icon/reorderable_hbox_icon.svg"))
|
||||
|
||||
|
||||
func _exit_tree():
|
||||
remove_custom_type("ReorderableContainer")
|
||||
remove_custom_type("ReorderableVBox")
|
||||
remove_custom_type("ReorderableHBox")
|
||||
1
addons/ReorderableContainer/plugin.gd.uid
Normal file
1
addons/ReorderableContainer/plugin.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://0uea0ywilkmu
|
||||
357
addons/ReorderableContainer/reorderable_container.gd
Normal file
357
addons/ReorderableContainer/reorderable_container.gd
Normal file
@@ -0,0 +1,357 @@
|
||||
@tool
|
||||
@icon("Icon/reorderable_container_icon.svg")
|
||||
class_name ReorderableContainer
|
||||
extends Container
|
||||
## A container that allows its child to be reorder and arranges horizontally or vertically.
|
||||
##
|
||||
## A container similar to [BoxContainer] but extended with drag-and-drop style reordering functionality,
|
||||
## and auto-scroll functionality when placed under [ScrollContainer].[br][br]
|
||||
## [b]Note:[/b] This addon also works with SmoothScroll by SpyrexDE.
|
||||
##
|
||||
## @tutorial(SmoothScroll): https://github.com/SpyrexDE/SmoothScroll
|
||||
## @tutorial(Using Containers): https://docs.godotengine.org/en/4.1/tutorials/ui/gui_containers.html
|
||||
|
||||
## Emitted when children have been reordered.
|
||||
signal reordered(from: int, to: int)
|
||||
signal dragging(pos: Vector2)
|
||||
signal drag_started(node)
|
||||
signal drag_stopped(node)
|
||||
## Extend the drop zone length at the start and end of the container.
|
||||
## This will ensure that drop input is recognized even outside the container itself.
|
||||
const DROP_ZONE_EXTEND = 2000
|
||||
|
||||
## The hold duration time in seconds before the holded child will start being drag.
|
||||
@export
|
||||
var hold_duration := 0.5
|
||||
|
||||
## The overall speed of how fast children will move and arrange.
|
||||
@export_range(3, 30, 0.01, "or_greater", "or_less")
|
||||
var speed := 10.0
|
||||
|
||||
## The space between the container's elements, in pixels.
|
||||
@export
|
||||
var separation := 10: set = set_separation
|
||||
func set_separation(value):
|
||||
if value == separation or value < 0:
|
||||
return
|
||||
separation = value
|
||||
_on_sort_children()
|
||||
|
||||
|
||||
## if [code]true[/code] the container will arrange its children vertically, rather than horizontally.
|
||||
@export var is_vertical := false: set = set_vertical
|
||||
func set_vertical(value):
|
||||
if value == is_vertical:
|
||||
return
|
||||
is_vertical = value
|
||||
if is_vertical:
|
||||
custom_minimum_size.x = 0
|
||||
else:
|
||||
custom_minimum_size.y = 0
|
||||
_on_sort_children()
|
||||
|
||||
## (Optional) [ScrollContainer] refference. Normally, the addon will automatically check
|
||||
## its parent node for [ScrollContainer]. If this is not the case, you can manually specify it here.
|
||||
@export
|
||||
var scroll_container: ScrollContainer
|
||||
|
||||
## The maximum speed of auto scroll.
|
||||
@export
|
||||
var auto_scroll_speed := 10.0
|
||||
|
||||
## The pacentage of how much space auto scroll will take in [ScrollContainer][br][br]
|
||||
## [b]Example:[/b] If [code]auto_scroll_range[/code] is 30% (0.3) and [ScrollContainer] height is 100 px,
|
||||
## upper part will be 0 to 30 px and lower part will be 70 to 100 px.
|
||||
@export_range(0, 0.5)
|
||||
var auto_scroll_range := 0.3
|
||||
|
||||
## The scrolling threshold in pixel. In a nutshell, user will have hard time trying to drag a child if it too low
|
||||
## and user will accidentally drag a child when scrolling if it too high.
|
||||
@export
|
||||
var scroll_threshold := 30
|
||||
|
||||
## Uses when debugging
|
||||
@export
|
||||
var is_debugging := false
|
||||
|
||||
var _scroll_starting_point := 0
|
||||
var _is_smooth_scroll := false
|
||||
|
||||
var _drop_zones: Array[Rect2] = []
|
||||
var _drop_zone_index := -1
|
||||
var _expect_child_rect: Array[Rect2] = []
|
||||
|
||||
var _focus_child: Control
|
||||
var _is_press := false
|
||||
var _is_hold := false
|
||||
var _current_duration := 0.0
|
||||
var _is_using_process := false
|
||||
|
||||
|
||||
func _ready():
|
||||
if scroll_container == null and get_parent() is ScrollContainer:
|
||||
scroll_container = get_parent()
|
||||
|
||||
if scroll_container != null and scroll_container.has_method("handle_overdrag"):
|
||||
_is_smooth_scroll = true
|
||||
|
||||
process_mode = Node.PROCESS_MODE_PAUSABLE
|
||||
_adjust_expected_child_rect()
|
||||
if not sort_children.is_connected(_on_sort_children):
|
||||
sort_children.connect(_on_sort_children, CONNECT_PERSIST)
|
||||
if not get_tree().node_added.is_connected(_on_node_added):
|
||||
get_tree().node_added.connect(_on_node_added, CONNECT_PERSIST)
|
||||
|
||||
|
||||
func _gui_input(event):
|
||||
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
|
||||
for _child in get_children():
|
||||
var child := _child as Control
|
||||
if child.get_rect().has_point(get_local_mouse_position()) and event.is_pressed():
|
||||
_focus_child = child
|
||||
_is_press = true
|
||||
elif not event.is_pressed():
|
||||
_is_press = false
|
||||
_is_hold = false
|
||||
|
||||
|
||||
func _process(delta):
|
||||
if Engine.is_editor_hint(): return
|
||||
|
||||
_handle_input(delta)
|
||||
if _current_duration >= hold_duration != _is_hold:
|
||||
_is_hold = _current_duration >= hold_duration
|
||||
if _is_hold:
|
||||
_on_start_dragging()
|
||||
|
||||
if _is_hold:
|
||||
_handle_dragging_child_pos(delta)
|
||||
if scroll_container != null:
|
||||
_handle_auto_scroll(delta)
|
||||
elif not _is_hold and _drop_zone_index != -1:
|
||||
_on_stop_dragging()
|
||||
|
||||
if _is_using_process :
|
||||
_on_sort_children(delta)
|
||||
|
||||
|
||||
func _handle_input(delta):
|
||||
if scroll_container != null and _is_press and not _is_hold:
|
||||
var scroll_point = scroll_container.scroll_vertical if is_vertical else scroll_container.scroll_horizontal
|
||||
if _current_duration == 0:
|
||||
_scroll_starting_point = scroll_point
|
||||
else:
|
||||
# If user scroll more than scroll_threshold, press is abort.
|
||||
_is_press = true if abs(scroll_point - _scroll_starting_point) <= scroll_threshold else false
|
||||
_current_duration = _current_duration + delta if _is_press else 0.0
|
||||
|
||||
|
||||
func _on_start_dragging():
|
||||
# Force _on_sort_children to use process update for linear interpolation
|
||||
_is_using_process = true
|
||||
_focus_child.z_index = 1
|
||||
# Workaround for SmoothScroll addon
|
||||
if _is_smooth_scroll:
|
||||
scroll_container.process_mode = Node.PROCESS_MODE_DISABLED
|
||||
for child in _get_visible_children():
|
||||
child.propagate_call("set_mouse_filter", [MOUSE_FILTER_IGNORE])
|
||||
drag_started.emit(_focus_child)
|
||||
|
||||
|
||||
|
||||
func _on_stop_dragging():
|
||||
_focus_child.z_index = 0
|
||||
var focus_child_index := _focus_child.get_index()
|
||||
move_child(_focus_child, _drop_zone_index)
|
||||
reordered.emit(focus_child_index, _drop_zone_index)
|
||||
drag_stopped.emit(_focus_child)
|
||||
_focus_child = null
|
||||
_drop_zone_index = -1
|
||||
if _is_smooth_scroll:
|
||||
scroll_container.pos = -Vector2(scroll_container.scroll_horizontal, scroll_container.scroll_vertical)
|
||||
scroll_container.process_mode = Node.PROCESS_MODE_INHERIT
|
||||
for child in _get_visible_children():
|
||||
child.propagate_call("set_mouse_filter", [MOUSE_FILTER_PASS])
|
||||
|
||||
|
||||
func _on_node_added(node):
|
||||
if node is Control and not Engine.is_editor_hint():
|
||||
node.mouse_filter = Control.MOUSE_FILTER_PASS
|
||||
|
||||
|
||||
func _handle_dragging_child_pos(delta):
|
||||
if is_vertical:
|
||||
var target_pos = get_local_mouse_position().y - (_focus_child.size.y / 2.0)
|
||||
_focus_child.position.y = lerp(_focus_child.position.y, target_pos, delta * speed)
|
||||
else:
|
||||
var target_pos = get_local_mouse_position().x - (_focus_child.size.x / 2.0)
|
||||
_focus_child.position.x = lerp(_focus_child.position.x, target_pos, delta * speed)
|
||||
|
||||
# Update drop zone index
|
||||
var child_center_pos: Vector2 = _focus_child.get_rect().get_center()
|
||||
for i in range(_drop_zones.size()):
|
||||
var drop_zone = _drop_zones[i]
|
||||
if drop_zone.has_point(child_center_pos):
|
||||
_drop_zone_index = i
|
||||
break
|
||||
elif i == _drop_zones.size() - 1:
|
||||
_drop_zone_index = -1
|
||||
dragging.emit(get_global_mouse_position())
|
||||
|
||||
func _handle_auto_scroll(delta):
|
||||
var mouse_g_pos = get_global_mouse_position()
|
||||
var scroll_g_rect = scroll_container.get_global_rect()
|
||||
if is_vertical:
|
||||
var upper = scroll_g_rect.position.y + (scroll_g_rect.size.y * auto_scroll_range)
|
||||
var lower = scroll_g_rect.position.y + (scroll_g_rect.size.y * (1.0 - auto_scroll_range))
|
||||
|
||||
if upper > mouse_g_pos.y:
|
||||
var factor = (upper - mouse_g_pos.y) / (upper - scroll_g_rect.position.y)
|
||||
scroll_container.scroll_vertical -= delta * float(auto_scroll_speed) * 150.0 * factor
|
||||
elif lower < mouse_g_pos.y:
|
||||
var factor = (mouse_g_pos.y - lower) / (scroll_g_rect.end.y - lower)
|
||||
scroll_container.scroll_vertical += delta * float(auto_scroll_speed) * 150.0 * factor
|
||||
else:
|
||||
scroll_container.scroll_vertical = scroll_container.scroll_vertical
|
||||
else:
|
||||
var left = scroll_g_rect.position.x + (scroll_g_rect.size.x * auto_scroll_range)
|
||||
var right = scroll_g_rect.position.x + (scroll_g_rect.size.x * (1.0 - auto_scroll_range))
|
||||
|
||||
if left > mouse_g_pos.x:
|
||||
var factor = (left - mouse_g_pos.x) / (left - scroll_g_rect.position.x)
|
||||
scroll_container.scroll_horizontal -= delta * float(auto_scroll_speed) * 150.0 * factor
|
||||
elif right < mouse_g_pos.x:
|
||||
var factor = (mouse_g_pos.x - right) / (scroll_g_rect.end.x - right)
|
||||
scroll_container.scroll_horizontal += delta * float(auto_scroll_speed) * 150.0 * factor
|
||||
else:
|
||||
scroll_container.scroll_horizontal = scroll_container.scroll_horizontal
|
||||
|
||||
|
||||
func _on_sort_children(delta := -1.0):
|
||||
if _is_using_process and delta == -1.0:
|
||||
return
|
||||
|
||||
_adjust_expected_child_rect()
|
||||
_adjust_child_rect(delta)
|
||||
_adjust_drop_zone_rect()
|
||||
|
||||
|
||||
func _adjust_expected_child_rect():
|
||||
_expect_child_rect.clear()
|
||||
var children := _get_visible_children()
|
||||
var end_point = 0.0
|
||||
for i in range(children.size()):
|
||||
var child := children[i]
|
||||
var min_size := child.get_combined_minimum_size()
|
||||
if is_vertical:
|
||||
if i == _drop_zone_index:
|
||||
end_point += _focus_child.size.y + separation
|
||||
|
||||
_expect_child_rect.append(Rect2(Vector2(0, end_point), Vector2(size.x, min_size.y)))
|
||||
end_point += min_size.y + separation
|
||||
else:
|
||||
if i == _drop_zone_index:
|
||||
end_point += _focus_child.size.x + separation
|
||||
|
||||
_expect_child_rect.append(Rect2(Vector2(end_point, 0), Vector2(min_size.x, size.y)))
|
||||
end_point += min_size.x + separation
|
||||
|
||||
|
||||
func _adjust_child_rect(delta: float = -1.0):
|
||||
var children := _get_visible_children()
|
||||
if children.is_empty():
|
||||
return
|
||||
|
||||
var is_animating := false
|
||||
var end_point := 0.0
|
||||
for i in range(children.size()):
|
||||
var child := children[i]
|
||||
if child.position == _expect_child_rect[i].position and child.size == _expect_child_rect[i].size:
|
||||
continue
|
||||
|
||||
if _is_using_process:
|
||||
is_animating = true
|
||||
child.position = lerp(child.position, _expect_child_rect[i].position, delta * speed)
|
||||
child.size = _expect_child_rect[i].size
|
||||
if (child.position - _expect_child_rect[i].position).length() <= 1.0:
|
||||
child.position = _expect_child_rect[i].position
|
||||
else:
|
||||
child.position = _expect_child_rect[i].position
|
||||
child.size = _expect_child_rect[i].size
|
||||
|
||||
var last_child := children[-1]
|
||||
if is_vertical:
|
||||
if _is_using_process and _drop_zone_index == children.size():
|
||||
custom_minimum_size.y = _expect_child_rect[-1].end.y + _focus_child.size.y + separation
|
||||
elif not _is_using_process:
|
||||
custom_minimum_size.y = last_child.get_rect().end.y
|
||||
else:
|
||||
if _is_using_process and _drop_zone_index == children.size():
|
||||
custom_minimum_size.x = _expect_child_rect[-1].end.x + _focus_child.size.x + separation
|
||||
elif not _is_using_process:
|
||||
custom_minimum_size.x = last_child.get_rect().end.x
|
||||
|
||||
# Adjust rect every process frame until child is dropped and finished lerping
|
||||
# ( return to adjust when sort_children signal is emitted)
|
||||
if not is_animating and _focus_child == null:
|
||||
_is_using_process = false
|
||||
|
||||
|
||||
func _adjust_drop_zone_rect():
|
||||
_drop_zones.clear()
|
||||
var children = _get_visible_children()
|
||||
for i in range(children.size()):
|
||||
var drop_zone_rect: Rect2
|
||||
var child := children[i] as Control
|
||||
if is_vertical:
|
||||
if i == 0:
|
||||
# First child
|
||||
drop_zone_rect.position = Vector2(child.position.x, child.position.y - DROP_ZONE_EXTEND)
|
||||
drop_zone_rect.end = Vector2(child.size.x, child.get_rect().get_center().y)
|
||||
_drop_zones.append(drop_zone_rect)
|
||||
else:
|
||||
# In between
|
||||
var prev_child := children[i - 1] as Control
|
||||
drop_zone_rect.position = Vector2(prev_child.position.x, prev_child.get_rect().get_center().y)
|
||||
drop_zone_rect.end = Vector2(child.size.x, child.get_rect().get_center().y)
|
||||
_drop_zones.append(drop_zone_rect)
|
||||
if i == children.size() - 1:
|
||||
# Is also last child
|
||||
drop_zone_rect.position = Vector2(child.position.x, child.get_rect().get_center().y)
|
||||
drop_zone_rect.end = Vector2(child.size.x, child.get_rect().end.y + DROP_ZONE_EXTEND)
|
||||
_drop_zones.append(drop_zone_rect)
|
||||
else:
|
||||
if i == 0:
|
||||
# First child
|
||||
drop_zone_rect.position = Vector2(child.position.x - DROP_ZONE_EXTEND, child.position.y)
|
||||
drop_zone_rect.end = Vector2(child.get_rect().get_center().x, child.size.y)
|
||||
_drop_zones.append(drop_zone_rect)
|
||||
else:
|
||||
# In between
|
||||
var prev_child := children[i - 1] as Control
|
||||
drop_zone_rect.position = Vector2(prev_child.get_rect().get_center().x, prev_child.position.y)
|
||||
drop_zone_rect.end = Vector2(child.get_rect().get_center().x, child.size.y)
|
||||
_drop_zones.append(drop_zone_rect)
|
||||
if i == children.size() - 1:
|
||||
# Is also last child
|
||||
drop_zone_rect.position = Vector2(child.get_rect().get_center().x, child.position.y)
|
||||
drop_zone_rect.end = Vector2(child.get_rect().end.x + DROP_ZONE_EXTEND, child.size.y)
|
||||
_drop_zones.append(drop_zone_rect)
|
||||
|
||||
|
||||
func _get_visible_children() -> Array[Control]:
|
||||
var visible_control: Array[Control]
|
||||
for _child in get_children():
|
||||
var child := _child as Control
|
||||
if not child.visible:
|
||||
continue
|
||||
if child == _focus_child and _is_hold:
|
||||
continue
|
||||
|
||||
visible_control.append(child)
|
||||
return visible_control
|
||||
|
||||
|
||||
func _print_debug(val):
|
||||
if is_debugging:
|
||||
print(val)
|
||||
1
addons/ReorderableContainer/reorderable_container.gd.uid
Normal file
1
addons/ReorderableContainer/reorderable_container.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://jwjxetmu7o2o
|
||||
13
addons/ReorderableContainer/reorderable_hbox.gd
Normal file
13
addons/ReorderableContainer/reorderable_hbox.gd
Normal file
@@ -0,0 +1,13 @@
|
||||
@tool
|
||||
@icon("Icon/reorderable_hbox_icon.svg")
|
||||
class_name ReorderableHBox
|
||||
extends ReorderableContainer
|
||||
|
||||
func set_vertical(value):
|
||||
value = false
|
||||
super.set_vertical(value)
|
||||
|
||||
|
||||
func _ready():
|
||||
is_vertical = false
|
||||
super._ready()
|
||||
1
addons/ReorderableContainer/reorderable_hbox.gd.uid
Normal file
1
addons/ReorderableContainer/reorderable_hbox.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://gp5cpsm0gdkx
|
||||
13
addons/ReorderableContainer/reorderable_vbox.gd
Normal file
13
addons/ReorderableContainer/reorderable_vbox.gd
Normal file
@@ -0,0 +1,13 @@
|
||||
@tool
|
||||
@icon("Icon/reorderable_vbox_icon.svg")
|
||||
class_name ReorderableVBox
|
||||
extends ReorderableContainer
|
||||
|
||||
func set_vertical(value):
|
||||
value = true
|
||||
super.set_vertical(value)
|
||||
|
||||
|
||||
func _ready():
|
||||
is_vertical = true
|
||||
super._ready()
|
||||
1
addons/ReorderableContainer/reorderable_vbox.gd.uid
Normal file
1
addons/ReorderableContainer/reorderable_vbox.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://d3mey1366662n
|
||||
Reference in New Issue
Block a user