Skip to content

Commit

Permalink
Merge pull request #49 from HaroldLever/godot-4
Browse files Browse the repository at this point in the history
Add scroll dampers
  • Loading branch information
SpyrexDE authored Apr 7, 2024
2 parents 9fa41fd + 3ecd2b5 commit 167ef98
Show file tree
Hide file tree
Showing 11 changed files with 603 additions and 209 deletions.
507 changes: 300 additions & 207 deletions addons/SmoothScroll/SmoothScrollContainer.gd

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion addons/SmoothScroll/plugin.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ name="SmoothScroll"
description="""This plugin adds a new scroll container class
with additional smooth scroll options."""
author="Fabian Keßler (SpyrexDE)"
version="1.2"
version="1.3"
script="plugin.gd"
33 changes: 33 additions & 0 deletions addons/SmoothScroll/scroll_damper/cubic_scroll_damper.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
extends ScrollDamper
class_name CubicScrollDamper


## Friction, not physical.
## The higher the value, the more obvious the deceleration.
@export_range(0.001, 10000.0, 0.001, "or_greater", "hide_slider")
var friction := 4.0:
set(val):
friction = max(val, 0.001)
_factor = pow(10.0, friction) - 1.0

## Factor to use in formula
var _factor := 10000.0:
set(val): _factor = max(val, 0.000000000001)


func _calculate_velocity_by_time(time: float) -> float:
if time <= 0.0: return 0.0
return time*time*time * _factor


func _calculate_time_by_velocity(velocity: float) -> float:
return pow(abs(velocity) / _factor, 1.0/3.0)


func _calculate_offset_by_time(time: float) -> float:
time = max(time, 0.0)
return 1.0/4.0 * _factor * time*time*time*time


func _calculate_time_by_offset(offset: float) -> float:
return pow(abs(offset) * 4.0 / _factor, 1.0/4.0)
47 changes: 47 additions & 0 deletions addons/SmoothScroll/scroll_damper/expo_scroll_damper.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
extends ScrollDamper
class_name ExpoScrollDamper


## Friction, not physical.
## The higher the value, the more obvious the deceleration.
@export_range(0.001, 10000.0, 0.001, "or_greater", "hide_slider")
var friction := 4.0:
set(val):
friction = max(val, 0.001)
_factor = pow(10.0, friction)

## Factor to use in formula
var _factor := 10000.0:
set(val): _factor = max(val, 1.000000000001)

## Minumun velocity.
@export_range(0.001, 100000.0, 0.001, "or_greater", "hide_slider")
var minimum_velocity := 0.4:
set(val): minimum_velocity = max(val, 0.001)


func _calculate_velocity_by_time(time: float) -> float:
var minimum_time = _calculate_time_by_velocity(minimum_velocity)
if time <= minimum_time: return 0.0
return pow(_factor, time)


func _calculate_time_by_velocity(velocity: float) -> float:
return log(abs(velocity)) / log(_factor)


func _calculate_offset_by_time(time: float) -> float:
return pow(_factor, time) / log(_factor)


func _calculate_time_by_offset(offset: float) -> float:
return log(offset * log(_factor)) / log(_factor)


func _calculate_velocity_to_dest(from: float, to: float) -> float:
var dist = to - from
var min_time = _calculate_time_by_velocity(minimum_velocity)
var min_offset = _calculate_offset_by_time(min_time)
var time = _calculate_time_by_offset(abs(dist) + min_offset)
var vel = _calculate_velocity_by_time(time) * sign(dist)
return vel
Binary file not shown.
29 changes: 29 additions & 0 deletions addons/SmoothScroll/scroll_damper/icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 37 additions & 0 deletions addons/SmoothScroll/scroll_damper/icon.svg.import
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[remap]

importer="texture"
type="CompressedTexture2D"
uid="uid://4ok12qtgl7xq"
path="res://.godot/imported/icon.svg-ab15342a73e61a79c8b3960fca89a8c3.ctex"
metadata={
"vram_texture": false
}

[deps]

source_file="res://addons/SmoothScroll/scroll_damper/icon.svg"
dest_files=["res://.godot/imported/icon.svg-ab15342a73e61a79c8b3960fca89a8c3.ctex"]

[params]

compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
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/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
33 changes: 33 additions & 0 deletions addons/SmoothScroll/scroll_damper/linear_scroll_damper.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
extends ScrollDamper
class_name LinearScrollDamper


## Friction, not physical.
## The higher the value, the more obvious the deceleration.
@export_range(0.001, 10000.0, 0.001, "or_greater", "hide_slider")
var friction := 4.0:
set(val):
friction = max(val, 0.001)
_factor = pow(10.0, friction) - 1.0

## Factor to use in formula
var _factor := 10000.0:
set(val): _factor = max(val, 0.000000000001)


func _calculate_velocity_by_time(time: float) -> float:
if time <= 0.0: return 0.0
return time * _factor


func _calculate_time_by_velocity(velocity: float) -> float:
return abs(velocity) / _factor


func _calculate_offset_by_time(time: float) -> float:
time = max(time, 0.0)
return 1.0/2.0 * _factor * time*time


func _calculate_time_by_offset(offset: float) -> float:
return sqrt(abs(offset) * 2.0 / _factor)
33 changes: 33 additions & 0 deletions addons/SmoothScroll/scroll_damper/quad_scroll_damper.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
extends ScrollDamper
class_name QuadScrollDamper


## Friction, not physical.
## The higher the value, the more obvious the deceleration.
@export_range(0.001, 10000.0, 0.001, "or_greater", "hide_slider")
var friction := 4.0:
set(val):
friction = max(val, 0.001)
_factor = pow(10.0, friction) - 1.0

## Factor to use in formula
var _factor := 10000.0:
set(val): _factor = max(val, 0.000000000001)


func _calculate_velocity_by_time(time: float) -> float:
if time <= 0.0: return 0.0
return time*time * _factor


func _calculate_time_by_velocity(velocity: float) -> float:
return sqrt(abs(velocity) / _factor)


func _calculate_offset_by_time(time: float) -> float:
time = max(time, 0.0)
return 1.0/3.0 * _factor * time*time*time


func _calculate_time_by_offset(offset: float) -> float:
return pow(abs(offset) * 3.0 / _factor, 1.0/3.0)
74 changes: 74 additions & 0 deletions addons/SmoothScroll/scroll_damper/scroll_damper.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
@icon("icon.svg")
extends Resource
class_name ScrollDamper

## Abstract class

## Rebound strength. The higher the value, the faster it attracts.
@export_range(0.0, 1.0, 0.001, "or_greater", "hide_slider")
var rebound_strength := 7.0:
set(val):
rebound_strength= max(val, 0.0)
_attract_factor = rebound_strength * rebound_strength * rebound_strength

## Factor for attracting.
var _attract_factor := 400.0:
set(val):
_attract_factor = max(val, 0.0)


# Abstract method
func _calculate_velocity_by_time(time: float) -> float:
return 0.0

# Abstract method
func _calculate_time_by_velocity(velocity: float) -> float:
return 0.0

# Abstract method
func _calculate_offset_by_time(time: float) -> float:
return 0.0

# Abstract method
func _calculate_time_by_offset(offset: float) -> float:
return 0.0


func _calculate_velocity_to_dest(from: float, to: float) -> float:
var dist = to - from
var time = _calculate_time_by_offset(abs(dist))
var vel = _calculate_velocity_by_time(time) * sign(dist)
return vel


func _calculate_next_velocity(present_time: float, delta_time: float) -> float:
return _calculate_velocity_by_time(present_time - delta_time)


func _calculate_next_offset(present_time: float, delta_time: float) -> float:
return _calculate_offset_by_time(present_time) \
- _calculate_offset_by_time(present_time - delta_time)


## Return the result of next velocity and position according to delta time
func slide(velocity: float, delta_time: float) -> Array:
var present_time = _calculate_time_by_velocity(velocity)
return [
_calculate_next_velocity(present_time, delta_time) * sign(velocity),
_calculate_next_offset(present_time, delta_time) * sign(velocity)
]


## Emulate force that attracts something to destination.
## Return the result of next velocity according to delta time
func attract(from: float, to: float, velocity: float, delta_time: float) -> float:
var dist = to - from
var target_vel = _calculate_velocity_to_dest(from, to)
velocity += _attract_factor * dist * delta_time \
+ _calculate_velocity_by_time(delta_time) * sign(dist)
if (
(dist > 0 and velocity >= target_vel) \
or (dist < 0 and velocity <= target_vel) \
):
velocity = target_vel
return velocity
17 changes: 16 additions & 1 deletion example.tscn
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[gd_scene load_steps=4 format=3 uid="uid://xqy4fhlaf2q3"]
[gd_scene load_steps=7 format=3 uid="uid://xqy4fhlaf2q3"]

[ext_resource type="Script" path="res://addons/SmoothScroll/SmoothScrollContainer.gd" id="1_su8ig"]
[ext_resource type="Script" path="res://addons/SmoothScroll/scroll_damper/expo_scroll_damper.gd" id="2_ibjlc"]

[sub_resource type="GDScript" id="GDScript_xo176"]
script/source = "extends Control
Expand All @@ -15,6 +16,18 @@ func _on_h_slider_value_changed(value):
$Label.text = \"FPS: \" + str($HSlider.value)
"

[sub_resource type="Resource" id="Resource_lssh0"]
script = ExtResource("2_ibjlc")
friction = 4.0
minimum_velocity = 0.4
rebound_strength = 7.0

[sub_resource type="Resource" id="Resource_nvbjt"]
script = ExtResource("2_ibjlc")
friction = 4.0
minimum_velocity = 0.4
rebound_strength = 7.0

[sub_resource type="GDScript" id="GDScript_xu50n"]
script/source = "extends RichTextLabel

Expand Down Expand Up @@ -63,6 +76,8 @@ offset_top = 147.0
offset_right = 649.0
offset_bottom = 393.0
script = ExtResource("1_su8ig")
wheel_scroll_damper = SubResource("Resource_lssh0")
dragging_scroll_damper = SubResource("Resource_nvbjt")
debug_mode = true
[node name="Control" type="Control" parent="SmoothScrollContainer"]
Expand Down

0 comments on commit 167ef98

Please sign in to comment.