1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-01-18 00:59:47 +00:00

Add presets to the curve edit widget

This commit is contained in:
Emmanouil Papadeas 2024-12-15 20:46:07 +02:00
parent cf8dacf0f5
commit 482dbecd13
4 changed files with 143 additions and 27 deletions

View file

@ -2,19 +2,19 @@
[ext_resource type="PackedScene" uid="uid://bybqhhayl5ay5" path="res://src/UI/Dialogs/ImageEffects/ImageEffectParent.tscn" id="1_4g7xo"]
[ext_resource type="Script" path="res://src/UI/Dialogs/ImageEffects/ColorCurvesDialog.gd" id="2_xkivc"]
[ext_resource type="Script" path="res://src/UI/Nodes/CurveEditor/CurveEdit.gd" id="3_fp0lm"]
[ext_resource type="Script" path="res://src/UI/Nodes/CurveEditor/CurveEdit.gd" id="3_3yyhs"]
[sub_resource type="Curve" id="Curve_p6hdh"]
[sub_resource type="Curve" id="Curve_gvi51"]
_data = [Vector2(0, 0), 0.0, 1.0, 0, 1, Vector2(1, 1), 1.0, 0.0, 1, 0]
point_count = 2
[node name="ColorCurvesDialog" instance=ExtResource("1_4g7xo")]
title = "Color Curves"
size = Vector2i(362, 440)
size = Vector2i(362, 481)
script = ExtResource("2_xkivc")
[node name="VBoxContainer" parent="." index="3"]
offset_bottom = 391.0
offset_bottom = 432.0
[node name="ShowAnimate" parent="VBoxContainer" index="0"]
visible = false
@ -51,10 +51,11 @@ popup/item_6/id = 6
popup/item_7/text = "Value"
popup/item_7/id = 7
[node name="CurveEdit" type="Control" parent="VBoxContainer" index="4"]
[node name="CurveEdit" type="VBoxContainer" parent="VBoxContainer" index="4"]
custom_minimum_size = Vector2(32, 150)
layout_mode = 2
size_flags_vertical = 3
script = ExtResource("3_fp0lm")
curve = SubResource("Curve_p6hdh")
script = ExtResource("3_3yyhs")
curve = SubResource("Curve_gvi51")
[connection signal="item_selected" from="VBoxContainer/ColorOptions/ChannelOptionButton" to="." method="_on_channel_option_button_item_selected"]

View file

@ -18,7 +18,8 @@ var max_y: float
var left_slope: CurveEditTangentPoint
var right_slope: CurveEditTangentPoint
@onready var parent := get_parent() as CurveEdit
@onready var parent := get_parent() as Control
@onready var grandparent := parent.get_parent() as CurveEdit
func _ready() -> void:
@ -45,7 +46,7 @@ func _draw() -> void:
func initialize(curve: Curve, index: int) -> void:
if not is_instance_valid(parent):
await ready
position = parent.transform_point(curve.get_point_position(index)) - OFFSET
position = grandparent.transform_point(curve.get_point_position(index)) - OFFSET
var left_tangent := curve.get_point_left_tangent(index)
var right_tangent := curve.get_point_right_tangent(index)
if left_tangent != INF:
@ -81,7 +82,7 @@ func _on_gui_input(event: InputEvent) -> void:
moving = true
else:
moving = false
parent.update_controls()
grandparent.update_controls()
elif event.button_index == MOUSE_BUTTON_RIGHT and event.pressed:
removed.emit(get_index())
elif moving and event is InputEventMouseMotion:

View file

@ -6,7 +6,7 @@
# https://github.com/RodZill4/material-maker/blob/master/material_maker/widgets/curve_edit/curve_editor.gd
@tool
class_name CurveEdit
extends Control
extends VBoxContainer
signal value_changed(value: Curve)
@ -17,23 +17,111 @@ signal value_changed(value: Curve)
queue_redraw()
update_controls()
## Array of dictionaries of key [String] and value [Array] of type [CurveEdit.CurvePoint].
var presets: Array[Dictionary] = [
{"Linear": [CurvePoint.new(0.0, 0.0, 0.0, 1.0), CurvePoint.new(1.0, 1.0, 1.0, 0.0)]},
{
"Ease out":
[
CurvePoint.new(0.0, 0.0, 0.0, 4.0),
CurvePoint.new(0.292893, 0.707107, 1.0, 1.0),
CurvePoint.new(1.0, 1.0, 0.0, 0.0)
]
},
{
"Ease in out":
[
CurvePoint.new(0.0, 0.0, 0.0, 0.0),
CurvePoint.new(0.5, 0.5, 3.0, 3.0),
CurvePoint.new(1.0, 1.0, 0.0, 0.0)
]
},
{
"Ease in":
[
CurvePoint.new(0.0, 0.0, 0.0, 0.0),
CurvePoint.new(0.707107, 0.292893, 1.0, 1.0),
CurvePoint.new(1.0, 1.0, 4.0, 0.0)
]
},
{
"Sawtooth":
[
CurvePoint.new(0.0, 0.0, 0.0, 2.0),
CurvePoint.new(0.5, 1.0, 2.0, -2.0),
CurvePoint.new(1.0, 0.0, -2.0, 0.0)
]
},
{
"Bounce":
[
CurvePoint.new(0.0, 0.0, 0.0, 5.0),
CurvePoint.new(0.15, 0.65, 2.45201, 2.45201),
CurvePoint.new(0.5, 1.0, 0.0, 0.0),
CurvePoint.new(0.85, 0.65, -2.45201, -2.45201),
CurvePoint.new(1.0, 0.0, -5.0, 0.0)
]
},
{
"Bevel":
[
CurvePoint.new(0.0, 0.0, 0.0, 2.38507),
CurvePoint.new(0.292893, 0.707107, 2.34362, 0.428147),
CurvePoint.new(1.0, 1.0, 0.410866, 0.0)
]
}
]
var curve_editor := Control.new()
var hbox := HBoxContainer.new()
class CurvePoint:
var pos: Vector2
var left_tangent: float
var right_tangent: float
func _init(x: float, y: float, _left_tangent := 0.0, _right_tangent := 0.0) -> void:
pos = Vector2(x, y)
left_tangent = _left_tangent
right_tangent = _right_tangent
func _ready() -> void:
if not is_instance_valid(curve):
curve = Curve.new()
gui_input.connect(_on_gui_input)
if custom_minimum_size.is_zero_approx():
custom_minimum_size = Vector2(32, 150)
curve_editor.gui_input.connect(_on_gui_input)
resized.connect(_on_resize)
queue_redraw()
update_controls()
curve_editor.size_flags_vertical = Control.SIZE_EXPAND_FILL
add_child(curve_editor)
add_child(hbox)
var presets_button := MenuButton.new()
presets_button.text = "Presets"
presets_button.flat = false
presets_button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
presets_button.size_flags_horizontal = Control.SIZE_EXPAND_FILL
presets_button.get_popup().id_pressed.connect(_on_presets_item_selected)
for preset in presets:
presets_button.get_popup().add_item(preset.keys()[0])
var invert_button := Button.new()
invert_button.text = "Invert"
invert_button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
invert_button.size_flags_horizontal = Control.SIZE_EXPAND_FILL
invert_button.pressed.connect(_on_invert_button_pressed)
hbox.add_child(presets_button)
hbox.add_child(invert_button)
_on_resize.call_deferred()
func update_controls() -> void:
for c in get_children():
c.queue_free()
for c in curve_editor.get_children():
if c is CurveEditControlPoint:
c.queue_free()
for i in curve.point_count:
var p := curve.get_point_position(i)
var control_point := CurveEditControlPoint.new()
add_child(control_point)
curve_editor.add_child(control_point)
control_point.initialize(curve, i)
control_point.position = transform_point(p) - control_point.OFFSET
if i == 0 or i == curve.point_count - 1:
@ -41,7 +129,7 @@ func update_controls() -> void:
control_point.position.x,
control_point.position.x,
-control_point.OFFSET.y,
size.y - control_point.OFFSET.y
available_size().y - control_point.OFFSET.y
)
if i == 0:
control_point.set_control_point_visibility(true, false)
@ -51,7 +139,7 @@ func update_controls() -> void:
var min_x := transform_point(curve.get_point_position(i - 1)).x + 1
var max_x := transform_point(curve.get_point_position(i + 1)).x - 1
control_point.set_constraint(
min_x, max_x, -control_point.OFFSET.y, size.y - control_point.OFFSET.y
min_x, max_x, -control_point.OFFSET.y, available_size().y - control_point.OFFSET.y
)
control_point.moved.connect(_on_control_point_moved)
control_point.removed.connect(_on_control_point_removed)
@ -66,12 +154,18 @@ static func to_texture(from_curve: Curve, width := 256) -> CurveTexture:
return texture
func available_size() -> Vector2:
if curve_editor.size.is_zero_approx():
return Vector2.ONE
return curve_editor.size
func transform_point(p: Vector2) -> Vector2:
return (Vector2(0.0, 1.0) + Vector2(1.0, -1.0) * p) * size
return (Vector2(0.0, 1.0) + Vector2(1.0, -1.0) * p) * available_size()
func reverse_transform_point(p: Vector2) -> Vector2:
return Vector2(0.0, 1.0) + Vector2(1.0, -1.0) * p / size
return Vector2(0.0, 1.0) + Vector2(1.0, -1.0) * p / available_size()
func _draw() -> void:
@ -89,8 +183,8 @@ func _draw() -> void:
if show_axes:
for i in range(5):
var p := transform_point(0.25 * Vector2(i, i))
draw_line(Vector2(p.x, 0), Vector2(p.x, size.y - 1), axes_color)
draw_line(Vector2(0, p.y), Vector2(size.x - 1, p.y), axes_color)
draw_line(Vector2(p.x, 0), Vector2(p.x, available_size().y - 1), axes_color)
draw_line(Vector2(0, p.y), Vector2(available_size().x - 1, p.y), axes_color)
var points := PackedVector2Array()
for i in range(curve.point_count - 1):
var p1 := curve.get_point_position(i)
@ -117,16 +211,16 @@ func _draw() -> void:
func _on_control_point_moved(index: int) -> void:
var control_point := get_child(index) as CurveEditControlPoint
var control_point := curve_editor.get_child(index) as CurveEditControlPoint
var new_point := reverse_transform_point(control_point.position + control_point.OFFSET)
curve.set_point_offset(index, new_point.x)
curve.set_point_value(index, new_point.y)
if is_instance_valid(control_point.left_slope):
var slope_vector := control_point.left_slope.position / size
var slope_vector := control_point.left_slope.position / available_size()
if slope_vector.x != 0:
curve.set_point_left_tangent(index, -slope_vector.y / slope_vector.x)
if is_instance_valid(control_point.right_slope):
var slope_vector := control_point.right_slope.position / size
var slope_vector := control_point.right_slope.position / available_size()
if slope_vector.x != 0:
curve.set_point_right_tangent(index, -slope_vector.y / slope_vector.x)
queue_redraw()
@ -151,3 +245,23 @@ func _on_gui_input(event: InputEvent) -> void:
func _on_resize() -> void:
queue_redraw()
update_controls()
func _on_presets_item_selected(index: int) -> void:
curve.clear_points()
var preset_points: Array = presets[index].values()[0]
for point: CurvePoint in preset_points:
curve.add_point(point.pos, point.left_tangent, point.right_tangent)
curve = curve # Call setter
func _on_invert_button_pressed() -> void:
var copy_curve := curve.duplicate() as Curve
curve.clear_points()
for i in copy_curve.point_count:
var point := copy_curve.get_point_position(i)
point.y = 1.0 - point.y
var left_tangent := -copy_curve.get_point_left_tangent(i)
var right_tangent := -copy_curve.get_point_right_tangent(i)
curve.add_point(point, left_tangent, right_tangent)
curve = curve # Call setter

View file

@ -4,7 +4,7 @@
class_name CurveEditTangentPoint
extends Control
const OFFSET := -Vector2(0, 0)
const OFFSET := Vector2(0, 0)
@export var distance := 30