Implement SuiScroller
This commit is contained in:
parent
246536b89e
commit
f9875906af
6 changed files with 287 additions and 0 deletions
|
@ -6,6 +6,7 @@
|
||||||
[ext_resource type="PackedScene" uid="uid://1r7pvm0biuk7" path="res://SUI/scenesrc/SuiHeader.tscn" id="2_pcev0"]
|
[ext_resource type="PackedScene" uid="uid://1r7pvm0biuk7" path="res://SUI/scenesrc/SuiHeader.tscn" id="2_pcev0"]
|
||||||
[ext_resource type="PackedScene" uid="uid://bso65vpjqc4g4" path="res://SUI/scenesrc/SuiText.tscn" id="4_1lt1v"]
|
[ext_resource type="PackedScene" uid="uid://bso65vpjqc4g4" path="res://SUI/scenesrc/SuiText.tscn" id="4_1lt1v"]
|
||||||
[ext_resource type="Texture2D" uid="uid://beqhfqbyme6in" path="res://SUI/dist/example.png" id="4_12skp"]
|
[ext_resource type="Texture2D" uid="uid://beqhfqbyme6in" path="res://SUI/dist/example.png" id="4_12skp"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://b31tqrkh73to2" path="res://SUI/scenesrc/SuiScroller.tscn" id="6_6g04c"]
|
||||||
|
|
||||||
[node name="Test" type="Control"]
|
[node name="Test" type="Control"]
|
||||||
layout_mode = 3
|
layout_mode = 3
|
||||||
|
@ -47,3 +48,79 @@ offset_top = 368.0
|
||||||
offset_right = -6.0
|
offset_right = -6.0
|
||||||
offset_bottom = -8.0
|
offset_bottom = -8.0
|
||||||
text = "Button: Normal [b]Bold[/b] [i]Italic[/i] [b][i]Bold Italic[/i][/b] [code]Code -->[/code]"
|
text = "Button: Normal [b]Bold[/b] [i]Italic[/i] [b][i]Bold Italic[/i][/b] [code]Code -->[/code]"
|
||||||
|
|
||||||
|
[node name="SuiScroller" parent="." instance=ExtResource("6_6g04c")]
|
||||||
|
layout_mode = 1
|
||||||
|
offset_left = 11.0
|
||||||
|
offset_top = 8.0
|
||||||
|
offset_right = -662.0
|
||||||
|
offset_bottom = -324.0
|
||||||
|
|
||||||
|
[node name="Control" type="Control" parent="SuiScroller"]
|
||||||
|
anchors_preset = 0
|
||||||
|
offset_right = 273.5
|
||||||
|
offset_bottom = 194.5
|
||||||
|
|
||||||
|
[node name="ColorBlue" type="ColorRect" parent="SuiScroller/Control"]
|
||||||
|
layout_mode = 0
|
||||||
|
offset_right = 191.0
|
||||||
|
offset_bottom = 141.0
|
||||||
|
color = Color(0.310936, 0.514811, 0.811473, 1)
|
||||||
|
|
||||||
|
[node name="ColorTeal" type="ColorRect" parent="SuiScroller/Control"]
|
||||||
|
layout_mode = 0
|
||||||
|
offset_left = 322.0
|
||||||
|
offset_top = 33.0
|
||||||
|
offset_right = 535.0
|
||||||
|
offset_bottom = 174.0
|
||||||
|
color = Color(0.0305469, 0.474519, 0.382426, 1)
|
||||||
|
|
||||||
|
[node name="ColorOrange" type="ColorRect" parent="SuiScroller/Control"]
|
||||||
|
layout_mode = 0
|
||||||
|
offset_left = 121.0
|
||||||
|
offset_top = 180.0
|
||||||
|
offset_right = 262.0
|
||||||
|
offset_bottom = 409.0
|
||||||
|
color = Color(0.878086, 0.420512, 0.0292931, 1)
|
||||||
|
|
||||||
|
[node name="ColorBlurple" type="ColorRect" parent="SuiScroller/Control"]
|
||||||
|
layout_mode = 0
|
||||||
|
offset_left = 315.0
|
||||||
|
offset_top = 208.0
|
||||||
|
offset_right = 643.0
|
||||||
|
offset_bottom = 441.0
|
||||||
|
color = Color(0.448018, 0.409285, 0.95843, 1)
|
||||||
|
|
||||||
|
[node name="DotStart" type="ColorRect" parent="SuiScroller/Control"]
|
||||||
|
layout_mode = 1
|
||||||
|
offset_right = 2.0
|
||||||
|
offset_bottom = 2.0
|
||||||
|
color = Color(0.839216, 0.0196078, 0.196078, 1)
|
||||||
|
|
||||||
|
[node name="DotEnd" type="ColorRect" parent="SuiScroller/Control"]
|
||||||
|
layout_mode = 0
|
||||||
|
offset_left = 641.0
|
||||||
|
offset_top = 439.0
|
||||||
|
offset_right = 643.0
|
||||||
|
offset_bottom = 441.0
|
||||||
|
color = Color(0.839216, 0.0196078, 0.196078, 1)
|
||||||
|
|
||||||
|
[node name="SuiScroller2" parent="." instance=ExtResource("6_6g04c")]
|
||||||
|
layout_mode = 1
|
||||||
|
offset_left = 348.0
|
||||||
|
offset_top = 209.0
|
||||||
|
offset_right = -325.0
|
||||||
|
offset_bottom = -123.0
|
||||||
|
|
||||||
|
[node name="Control" type="Control" parent="SuiScroller2"]
|
||||||
|
anchors_preset = 0
|
||||||
|
offset_right = 273.5
|
||||||
|
offset_bottom = 194.5
|
||||||
|
|
||||||
|
[node name="ColorRed" type="ColorRect" parent="SuiScroller2/Control"]
|
||||||
|
layout_mode = 0
|
||||||
|
offset_left = 64.0
|
||||||
|
offset_top = 39.0
|
||||||
|
offset_right = 255.0
|
||||||
|
offset_bottom = 180.0
|
||||||
|
color = Color(0.834501, 0, 0.0728748, 1)
|
||||||
|
|
|
@ -21,6 +21,7 @@ boot_splash/show_image=false
|
||||||
|
|
||||||
window/size/viewport_width=960
|
window/size/viewport_width=960
|
||||||
window/size/viewport_height=540
|
window/size/viewport_height=540
|
||||||
|
window/size/resizable=false
|
||||||
|
|
||||||
[filesystem]
|
[filesystem]
|
||||||
|
|
||||||
|
|
36
sui/scenesrc/SuiScroller.tscn
Normal file
36
sui/scenesrc/SuiScroller.tscn
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
[gd_scene load_steps=3 format=3 uid="uid://b31tqrkh73to2"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://SUI/src/SuiScroller.gd" id="1_dcfql"]
|
||||||
|
[ext_resource type="Theme" uid="uid://jg7l68yqa6n2" path="res://SUI/themes/ScrollBar.tres" id="2_4lteo"]
|
||||||
|
|
||||||
|
[node name="SuiScroller" type="Control"]
|
||||||
|
clip_contents = true
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_right = -860.0
|
||||||
|
offset_bottom = -440.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
script = ExtResource("1_dcfql")
|
||||||
|
speed_value = 0.0
|
||||||
|
|
||||||
|
[node name="HScrollBar" type="HScrollBar" parent="."]
|
||||||
|
modulate = Color(1, 1, 1, 0.501961)
|
||||||
|
layout_mode = 1
|
||||||
|
offset_top = 86.5
|
||||||
|
offset_right = 86.5
|
||||||
|
offset_bottom = 100.0
|
||||||
|
theme = ExtResource("2_4lteo")
|
||||||
|
|
||||||
|
[node name="VScrollBar" type="VScrollBar" parent="."]
|
||||||
|
modulate = Color(1, 1, 1, 0.501961)
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 1
|
||||||
|
anchor_left = 1.0
|
||||||
|
anchor_right = 1.0
|
||||||
|
offset_left = -13.5
|
||||||
|
offset_bottom = 86.5
|
||||||
|
grow_horizontal = 0
|
||||||
|
theme = ExtResource("2_4lteo")
|
157
sui/src/SuiScroller.gd
Normal file
157
sui/src/SuiScroller.gd
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
@tool
|
||||||
|
extends SuiBaseClass
|
||||||
|
|
||||||
|
@export_category("Base Configuration")
|
||||||
|
@export_subgroup("Visibility")
|
||||||
|
@export var hscroll_visibility: SuiTypes.ScrollVisibility = SuiTypes.ScrollVisibility.AUTO
|
||||||
|
@export var vscroll_visibility: SuiTypes.ScrollVisibility = SuiTypes.ScrollVisibility.AUTO
|
||||||
|
@export_category("Advanced Configuration")
|
||||||
|
@export_subgroup("Scroller speed")
|
||||||
|
@export var speed_mode: SuiTypes.ScrollMode = SuiTypes.ScrollMode.MULTIPLY_CUSTOM_VALUE
|
||||||
|
@export var speed_multiplier: float = 1
|
||||||
|
@export var speed_value: float = 1
|
||||||
|
@export_subgroup("Scroller size")
|
||||||
|
@export var size_mode: SuiTypes.ScrollMode = SuiTypes.ScrollMode.MULTIPLY_VIEWPORT
|
||||||
|
@export var size_multiplier: float = 0.025
|
||||||
|
@export var size_value: float = 0
|
||||||
|
@export_category("Debugging")
|
||||||
|
@export var editor_clip_content: bool = true
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
super()
|
||||||
|
if !in_editor(): logger = core.logger.get_instance("SUI/src/SuiScroller.gd", self)
|
||||||
|
|
||||||
|
func update_element() -> void:
|
||||||
|
# Clip contents
|
||||||
|
if in_editor() and !editor_clip_content: clip_contents = false
|
||||||
|
else: clip_contents = true
|
||||||
|
|
||||||
|
# Update sizes and positions
|
||||||
|
match(size_mode):
|
||||||
|
SuiTypes.ScrollMode.MULTIPLY_VIEWPORT:
|
||||||
|
var window_size: Vector2i = Vector2i(ProjectSettings.get("display/window/size/viewport_width"), ProjectSettings.get("display/window/size/viewport_height"))
|
||||||
|
# Find smaller value
|
||||||
|
var scale_size: int
|
||||||
|
if window_size.x < window_size.y: scale_size = window_size.x
|
||||||
|
elif window_size.x > window_size.y: scale_size = window_size.y
|
||||||
|
|
||||||
|
$HScrollBar.size.y = scale_size*size_multiplier
|
||||||
|
$VScrollBar.size.x = scale_size*size_multiplier
|
||||||
|
SuiTypes.ScrollMode.MULTIPLY_CUSTOM_VALUE:
|
||||||
|
$HScrollBar.size.y = size_value*size_multiplier
|
||||||
|
$VScrollBar.size.x = size_value*size_multiplier
|
||||||
|
SuiTypes.ScrollMode.CUSTOM_VALUE:
|
||||||
|
$HScrollBar.size.y = size_value
|
||||||
|
$VScrollBar.size.x = size_value
|
||||||
|
$HScrollBar.size.x = size.x-$VScrollBar.size.x
|
||||||
|
$VScrollBar.size.y = size.y-$HScrollBar.size.y
|
||||||
|
$HScrollBar.position.x = 0
|
||||||
|
$HScrollBar.position.y = size.y-$HScrollBar.size.y
|
||||||
|
$VScrollBar.position.x = size.x-$VScrollBar.size.x
|
||||||
|
$VScrollBar.position.y = 0
|
||||||
|
|
||||||
|
# Update scrollbar properties
|
||||||
|
# Determine scroll speed
|
||||||
|
var speed: float
|
||||||
|
match(speed_mode):
|
||||||
|
SuiTypes.ScrollMode.MULTIPLY_VIEWPORT:
|
||||||
|
# Find smaller value
|
||||||
|
var scale_size: float
|
||||||
|
if size.x < size.y: scale_size = size.x
|
||||||
|
elif size.x > size.y: scale_size = size.y
|
||||||
|
|
||||||
|
speed = scale_size*speed_multiplier
|
||||||
|
SuiTypes.ScrollMode.MULTIPLY_CUSTOM_VALUE:
|
||||||
|
speed = speed_value*speed_multiplier
|
||||||
|
SuiTypes.ScrollMode.CUSTOM_VALUE:
|
||||||
|
speed = speed_value
|
||||||
|
# HScrollBar
|
||||||
|
$HScrollBar.step = speed
|
||||||
|
$HScrollBar.page = speed
|
||||||
|
# VScrollBar
|
||||||
|
$VScrollBar.step = speed
|
||||||
|
$VScrollBar.page = speed
|
||||||
|
|
||||||
|
# Update visibility
|
||||||
|
# HScrollBar
|
||||||
|
match(hscroll_visibility):
|
||||||
|
SuiTypes.ScrollVisibility.AUTO:
|
||||||
|
$HScrollBar.visible = true
|
||||||
|
$HScrollBar.modulate = Color8(255, 255, 255, 128)
|
||||||
|
SuiTypes.ScrollVisibility.SHOWN:
|
||||||
|
$HScrollBar.visible = true
|
||||||
|
$HScrollBar.modulate = Color8(255, 255, 255, 255)
|
||||||
|
SuiTypes.ScrollVisibility.HIDDEN: $HScrollBar.visible = false
|
||||||
|
_:
|
||||||
|
if in_editor(): printerr("Invalid hscroll_visibility value '" + str(hscroll_visibility) + "'")
|
||||||
|
else: logger.crash("Invalid hscroll_visibility value '" + str(hscroll_visibility) + "'")
|
||||||
|
# VScrollBar
|
||||||
|
match(vscroll_visibility):
|
||||||
|
SuiTypes.ScrollVisibility.AUTO:
|
||||||
|
$VScrollBar.visible = true
|
||||||
|
$VScrollBar.modulate = Color8(255, 255, 255, 128)
|
||||||
|
SuiTypes.ScrollVisibility.SHOWN:
|
||||||
|
$VScrollBar.visible = true
|
||||||
|
$VScrollBar.modulate = Color8(255, 255, 255, 255)
|
||||||
|
SuiTypes.ScrollVisibility.HIDDEN: $VScrollBar.visible = false
|
||||||
|
_:
|
||||||
|
if in_editor(): printerr("Invalid vscroll_visibility value '" + str(hscroll_visibility) + "'")
|
||||||
|
else: logger.crash("Invalid vscroll_visibility value '" + str(hscroll_visibility) + "'")
|
||||||
|
|
||||||
|
if in_editor() and get_child_count() == 3:
|
||||||
|
var container: Control = get_child(2)
|
||||||
|
|
||||||
|
# Update container position
|
||||||
|
container.position.x = 0
|
||||||
|
container.position.y = 0
|
||||||
|
return
|
||||||
|
|
||||||
|
# Move control
|
||||||
|
if get_child_count() == 3 and get_child(2) != $VScrollBar: move_child(get_child(2), 0)
|
||||||
|
|
||||||
|
# Make scrolling possible
|
||||||
|
if get_child_count() == 3 and get_child(0).is_class("Control"):
|
||||||
|
var container: Control = get_child(0)
|
||||||
|
var max_scrolling_distance: Vector2 = Vector2.ZERO
|
||||||
|
|
||||||
|
# Update container size
|
||||||
|
if vscroll_visibility == SuiTypes.ScrollVisibility.HIDDEN: container.size.x = size.x
|
||||||
|
else: container.size.x = size.x-$VScrollBar.size.x
|
||||||
|
if vscroll_visibility == SuiTypes.ScrollVisibility.HIDDEN: container.size.y = size.y
|
||||||
|
else: container.size.y = size.y-$HScrollBar.size.y
|
||||||
|
|
||||||
|
# Update container position
|
||||||
|
container.position.x = -$HScrollBar.value
|
||||||
|
container.position.y = -$VScrollBar.value
|
||||||
|
|
||||||
|
# Get max scrolling distance
|
||||||
|
for child in container.get_children(true):
|
||||||
|
# Ensure 'size' and 'position' variables are either a Vector2 or Vector2i if not of type Control.
|
||||||
|
if !child.is_class("Control"):
|
||||||
|
match(typeof(child.get("size"))):
|
||||||
|
Variant.Type.TYPE_VECTOR2: pass
|
||||||
|
Variant.Type.TYPE_VECTOR2I: pass
|
||||||
|
_: continue
|
||||||
|
match(typeof(child.get("position"))):
|
||||||
|
Variant.Type.TYPE_VECTOR2: pass
|
||||||
|
Variant.Type.TYPE_VECTOR2I: pass
|
||||||
|
_: continue
|
||||||
|
|
||||||
|
if child.size.x+child.position.x > max_scrolling_distance.x:
|
||||||
|
max_scrolling_distance.x = child.size.x+child.position.x-container.size.x
|
||||||
|
if child.size.y+child.position.y > max_scrolling_distance.y:
|
||||||
|
max_scrolling_distance.y = child.size.y+child.position.y-container.size.y
|
||||||
|
|
||||||
|
# Update scroll bar max value
|
||||||
|
$HScrollBar.max_value = max_scrolling_distance.x
|
||||||
|
$VScrollBar.max_value = max_scrolling_distance.y
|
||||||
|
else:
|
||||||
|
$HScrollBar.max_value = size.x
|
||||||
|
$VScrollBar.max_value = size.y
|
||||||
|
|
||||||
|
func _get_configuration_warnings():
|
||||||
|
if get_child_count() != 3:
|
||||||
|
return ["SuiScroller is intended to operate with one child only."]
|
||||||
|
elif !get_child(2).is_class("Control"):
|
||||||
|
return ["SuiScroller only supports Controls."]
|
||||||
|
return []
|
13
sui/src/SuiTypes.gd
Normal file
13
sui/src/SuiTypes.gd
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
extends Node
|
||||||
|
class_name SuiTypes
|
||||||
|
|
||||||
|
enum ScrollVisibility {
|
||||||
|
AUTO,
|
||||||
|
SHOWN,
|
||||||
|
HIDDEN
|
||||||
|
}
|
||||||
|
enum ScrollMode {
|
||||||
|
MULTIPLY_VIEWPORT,
|
||||||
|
MULTIPLY_CUSTOM_VALUE,
|
||||||
|
CUSTOM_VALUE
|
||||||
|
}
|
3
sui/themes/ScrollBar.tres
Normal file
3
sui/themes/ScrollBar.tres
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[gd_resource type="Theme" format=3 uid="uid://jg7l68yqa6n2"]
|
||||||
|
|
||||||
|
[resource]
|
Loading…
Reference in a new issue