Skip to content

Commit 3318c9b

Browse files
committed
Improve curve editor
1 parent 23463a3 commit 3318c9b

23 files changed

+426
-52
lines changed

addons/material_maker/types/curve.gd

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,17 @@ func compare(curve) -> bool:
3838
return false
3939
return true
4040

41-
func add_point(x : float, y : float, ls : float = INF, rs : float = INF) -> void:
41+
func add_point(x : float, y : float, ls : float = INF, rs : float = INF) -> int:
4242
for i in points.size():
4343
if x < points[i].p.x:
4444
if ls == INF:
4545
ls = 0
4646
if rs == INF:
4747
rs = 0
4848
points.insert(i, Point.new(x, y, ls, rs))
49-
return
49+
return i
5050
points.append(Point.new(x, y, ls, rs))
51+
return -1
5152

5253
func remove_point(index : int) -> bool:
5354
if index <= 0 or index >= points.size() - 1:

material_maker/widgets/curve_edit/control_point.gd

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,36 @@
11
extends Control
22

33
var moving : bool = false
4+
var hovering : bool = false
5+
var is_selected : bool = false
46

57
var min_x : float
68
var max_x : float
79
var min_y : float
810
var max_y : float
911

10-
const OFFSET : Vector2 = Vector2(3, 3)
12+
const OFFSET : Vector2 = Vector2(4, 4)
1113

1214
signal moved(index)
1315
signal removed(index)
16+
signal selected(index)
1417

1518
func _ready():
1619
pass # Replace with function body.
1720

1821
func _draw():
1922
var current_theme : Theme = mm_globals.main_window.theme
2023
var color : Color = current_theme.get_color("font_color", "Label")
24+
var selected_color : Color = current_theme.get_color("icon_pressed_color", "Button")
2125
for c in get_children():
2226
if c.visible:
23-
draw_line(OFFSET, c.position+OFFSET, color)
24-
draw_rect(Rect2(0, 0, 7, 7), color)
27+
draw_line(OFFSET, c.position+OFFSET, color, 0.5, true)
28+
draw_rect(Rect2(Vector2.ZERO, custom_minimum_size), selected_color if is_selected else color, true)
29+
draw_rect(Rect2(Vector2.ZERO, custom_minimum_size), color.inverted(), false)
30+
if hovering or moving:
31+
draw_rect(Rect2(-custom_minimum_size * 0.5, custom_minimum_size * 2.0), color, false, 1.0)
32+
draw_rect(Rect2(-custom_minimum_size*0.5-Vector2(1.0,1.0),
33+
custom_minimum_size*2.0+Vector2(2.0,2.0)), color.inverted(), false, 1.0)
2534

2635
func initialize(p : MMCurve.Point) -> void:
2736
position = get_parent().transform_point(p.p)-OFFSET
@@ -41,13 +50,27 @@ func _on_ControlPoint_gui_input(event):
4150
if event.button_index == MOUSE_BUTTON_LEFT:
4251
if event.pressed:
4352
moving = true
53+
is_selected = true
54+
emit_signal("selected", get_index())
55+
queue_redraw()
4456
else:
4557
moving = false
58+
is_selected = false
59+
queue_redraw()
4660
get_parent().update_controls()
4761
elif event.button_index == MOUSE_BUTTON_RIGHT and event.pressed:
4862
emit_signal("removed", get_index())
4963
elif moving and event is InputEventMouseMotion:
50-
position += event.relative
64+
var new_pos : Vector2 = position + event.relative
65+
if event.is_command_or_control_pressed():
66+
if get_parent().axes_density > 1.0:
67+
var snap : float = 1.0 / (get_parent().axes_density - 1.0)
68+
new_pos = position + (event.position - custom_minimum_size / 2.0)
69+
new_pos /= get_parent_control().size
70+
new_pos = snapped(new_pos, Vector2(snap, snap))
71+
new_pos *= get_parent_control().size
72+
new_pos -= custom_minimum_size/2.0
73+
position = new_pos
5174
if position.x < min_x:
5275
position.x = min_x
5376
elif position.x > max_x:
@@ -61,3 +84,14 @@ func _on_ControlPoint_gui_input(event):
6184
func update_tangents() -> void:
6285
queue_redraw()
6386
emit_signal("moved", get_index())
87+
emit_signal("selected", get_index())
88+
89+
90+
func _on_mouse_entered() -> void:
91+
queue_redraw()
92+
hovering = true
93+
94+
95+
func _on_mouse_exited() -> void:
96+
queue_redraw()
97+
hovering = false
Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,42 @@
11
[gd_scene load_steps=3 format=3 uid="uid://bhr7y7noxv5e6"]
22

3-
[ext_resource type="Script" path="res://material_maker/widgets/curve_edit/slope_point.gd" id="1"]
4-
[ext_resource type="Script" path="res://material_maker/widgets/curve_edit/control_point.gd" id="2"]
3+
[ext_resource type="Script" uid="uid://dl376nblfgqfs" path="res://material_maker/widgets/curve_edit/slope_point.gd" id="1"]
4+
[ext_resource type="Script" uid="uid://lfjxe7jh8oyu" path="res://material_maker/widgets/curve_edit/control_point.gd" id="2"]
55

66
[node name="ControlPoint" type="Control"]
7+
custom_minimum_size = Vector2(8, 8)
8+
layout_mode = 3
9+
anchors_preset = 0
710
offset_left = 56.9864
811
offset_top = 33.8615
912
offset_right = 63.9864
1013
offset_bottom = 40.8615
11-
custom_minimum_size = Vector2(7, 7)
1214
script = ExtResource("2")
13-
__meta__ = {
14-
"_edit_use_anchors_": false
15-
}
1615

1716
[node name="LeftSlope" type="Control" parent="."]
18-
offset_left = -18.5235
19-
offset_right = -11.5235
20-
offset_bottom = 7.0
2117
custom_minimum_size = Vector2(7, 7)
18+
anchors_preset = 0
19+
offset_left = -18.524
20+
offset_right = -11.524
21+
offset_bottom = 7.0
2222
script = ExtResource("1")
23-
__meta__ = {
24-
"_edit_use_anchors_": false
25-
}
2623
distance = -30.0
2724

2825
[node name="RightSlope" type="Control" parent="."]
29-
offset_left = 15.6919
30-
offset_right = 22.6919
26+
custom_minimum_size = Vector2(7, 7)
27+
anchors_preset = 0
28+
offset_left = 15.692
29+
offset_right = 22.692
3130
offset_bottom = 7.0
3231
script = ExtResource("1")
33-
__meta__ = {
34-
"_edit_use_anchors_": false
35-
}
3632
distance = 30.0
3733

3834
[connection signal="gui_input" from="." to="." method="_on_ControlPoint_gui_input"]
35+
[connection signal="mouse_entered" from="." to="." method="_on_mouse_entered"]
36+
[connection signal="mouse_exited" from="." to="." method="_on_mouse_exited"]
3937
[connection signal="gui_input" from="LeftSlope" to="LeftSlope" method="_on_ControlPoint_gui_input"]
38+
[connection signal="mouse_entered" from="LeftSlope" to="LeftSlope" method="_on_mouse_entered"]
39+
[connection signal="mouse_exited" from="LeftSlope" to="LeftSlope" method="_on_mouse_exited"]
4040
[connection signal="gui_input" from="RightSlope" to="RightSlope" method="_on_ControlPoint_gui_input"]
41+
[connection signal="mouse_entered" from="RightSlope" to="RightSlope" method="_on_mouse_entered"]
42+
[connection signal="mouse_exited" from="RightSlope" to="RightSlope" method="_on_mouse_exited"]

material_maker/widgets/curve_edit/curve_dialog.gd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,4 @@ func _on_Invert_pressed() -> void:
3636
for p in old_curve.points:
3737
new_curve.add_point(p.p.x, 1.0 - p.p.y, -p.ls, -p.rs)
3838
$VBoxContainer/EditorContainer/CurveEditor.set_curve(new_curve)
39+
$VBoxContainer/EditorContainer/CurveEditor.update_control_ui()

material_maker/widgets/curve_edit/curve_dialog.tscn

Lines changed: 106 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
[gd_scene load_steps=4 format=3 uid="uid://dmfusfaiojjvf"]
1+
[gd_scene load_steps=6 format=3 uid="uid://dmfusfaiojjvf"]
22

33
[ext_resource type="PackedScene" uid="uid://c2ns17avhb2nx" path="res://material_maker/widgets/curve_edit/curve_editor.tscn" id="1"]
4-
[ext_resource type="Script" path="res://material_maker/widgets/curve_edit/curve_dialog.gd" id="2"]
5-
[ext_resource type="Script" path="res://material_maker/widgets/curve_edit/presets_selector.gd" id="3"]
4+
[ext_resource type="Script" uid="uid://06osuiqfmilt" path="res://material_maker/widgets/curve_edit/curve_dialog.gd" id="2"]
5+
[ext_resource type="Script" uid="uid://pgn60kk5fcj6" path="res://material_maker/widgets/curve_edit/settings_panel.gd" id="2_fe25e"]
6+
[ext_resource type="Script" uid="uid://df24muo083lfx" path="res://material_maker/widgets/curve_edit/presets_selector.gd" id="3"]
7+
[ext_resource type="PackedScene" uid="uid://rflulhsuy3ax" path="res://material_maker/widgets/float_edit/float_edit.tscn" id="3_fe25e"]
68

79
[node name="CurveDialog" type="Window"]
810
title = "Edit curve"
11+
position = Vector2i(0, 36)
912
size = Vector2i(300, 300)
1013
exclusive = true
1114
min_size = Vector2i(300, 300)
@@ -20,16 +23,107 @@ offset_top = 5.0
2023
offset_right = -5.0
2124
offset_bottom = -5.0
2225

26+
[node name="CurveViewSettingsContainer" type="MarginContainer" parent="VBoxContainer"]
27+
layout_mode = 2
28+
theme_override_constants/margin_left = 12
29+
theme_override_constants/margin_top = 4
30+
31+
[node name="CurveViewSettings" type="PanelContainer" parent="VBoxContainer/CurveViewSettingsContainer"]
32+
layout_mode = 2
33+
size_flags_horizontal = 0
34+
theme_type_variation = &"MM_PanelMenuBar"
35+
script = ExtResource("2_fe25e")
36+
37+
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/CurveViewSettingsContainer/CurveViewSettings"]
38+
layout_mode = 2
39+
size_flags_horizontal = 0
40+
41+
[node name="GridLabel" type="Label" parent="VBoxContainer/CurveViewSettingsContainer/CurveViewSettings/HBoxContainer"]
42+
layout_mode = 2
43+
text = "Grid"
44+
45+
[node name="GridDensity" parent="VBoxContainer/CurveViewSettingsContainer/CurveViewSettings/HBoxContainer" instance=ExtResource("3_fe25e")]
46+
unique_name_in_owner = true
47+
layout_mode = 2
48+
value = 4.0
49+
min_value = 1.0
50+
max_value = 16.0
51+
step = 1.0
52+
float_only = true
53+
2354
[node name="EditorContainer" type="MarginContainer" parent="VBoxContainer"]
2455
clip_contents = true
2556
layout_mode = 2
2657
size_flags_horizontal = 3
2758
size_flags_vertical = 3
59+
theme_override_constants/margin_left = 12
60+
theme_override_constants/margin_top = 12
61+
theme_override_constants/margin_right = 12
62+
theme_override_constants/margin_bottom = 12
2863

2964
[node name="CurveEditor" parent="VBoxContainer/EditorContainer" instance=ExtResource("1")]
65+
unique_name_in_owner = true
3066
layout_mode = 2
3167
size_flags_vertical = 3
3268

69+
[node name="ControlUIContainer" type="VBoxContainer" parent="VBoxContainer"]
70+
custom_minimum_size = Vector2(0, 23)
71+
layout_mode = 2
72+
73+
[node name="ControlUI" type="HBoxContainer" parent="VBoxContainer/ControlUIContainer"]
74+
unique_name_in_owner = true
75+
visible = false
76+
layout_mode = 2
77+
size_flags_horizontal = 4
78+
79+
[node name="PositionLabel" type="Label" parent="VBoxContainer/ControlUIContainer/ControlUI"]
80+
layout_mode = 2
81+
text = "Position"
82+
83+
[node name="PositionX" parent="VBoxContainer/ControlUIContainer/ControlUI" instance=ExtResource("3_fe25e")]
84+
unique_name_in_owner = true
85+
custom_minimum_size = Vector2(70, 0)
86+
layout_mode = 2
87+
value = 1.0
88+
step = 0.01
89+
float_only = true
90+
91+
[node name="PositionY" parent="VBoxContainer/ControlUIContainer/ControlUI" instance=ExtResource("3_fe25e")]
92+
unique_name_in_owner = true
93+
custom_minimum_size = Vector2(70, 0)
94+
layout_mode = 2
95+
value = 0.0
96+
step = 0.01
97+
float_only = true
98+
99+
[node name="Spacer" type="Control" parent="VBoxContainer/ControlUIContainer/ControlUI"]
100+
custom_minimum_size = Vector2(12, 0)
101+
layout_mode = 2
102+
103+
[node name="SlopeLabel" type="Label" parent="VBoxContainer/ControlUIContainer/ControlUI"]
104+
layout_mode = 2
105+
text = "Handles"
106+
107+
[node name="LeftSlope" parent="VBoxContainer/ControlUIContainer/ControlUI" instance=ExtResource("3_fe25e")]
108+
unique_name_in_owner = true
109+
custom_minimum_size = Vector2(70, 0)
110+
layout_mode = 2
111+
value = 0.0
112+
min_value = -89.0
113+
max_value = 89.0
114+
step = 0.1
115+
float_only = true
116+
117+
[node name="RightSlope" parent="VBoxContainer/ControlUIContainer/ControlUI" instance=ExtResource("3_fe25e")]
118+
unique_name_in_owner = true
119+
custom_minimum_size = Vector2(70, 0)
120+
layout_mode = 2
121+
value = 45.0
122+
min_value = -89.0
123+
max_value = 89.0
124+
step = 0.1
125+
float_only = true
126+
33127
[node name="HSeparator" type="HSeparator" parent="VBoxContainer"]
34128
layout_mode = 2
35129

@@ -63,7 +157,16 @@ layout_mode = 2
63157
text = "Cancel"
64158

65159
[connection signal="close_requested" from="." to="." method="_on_Cancel_pressed"]
160+
[connection signal="ready" from="VBoxContainer/CurveViewSettingsContainer/CurveViewSettings" to="VBoxContainer/CurveViewSettingsContainer/CurveViewSettings" method="_on_ready"]
161+
[connection signal="value_changed" from="VBoxContainer/CurveViewSettingsContainer/CurveViewSettings/HBoxContainer/GridDensity" to="VBoxContainer/CurveViewSettingsContainer/CurveViewSettings" method="_on_grid_density_value_changed"]
66162
[connection signal="value_changed" from="VBoxContainer/EditorContainer/CurveEditor" to="." method="_on_CurveEditor_value_changed"]
163+
[connection signal="gui_input" from="VBoxContainer/EditorContainer/CurveEditor/@Control@283287" to="VBoxContainer/EditorContainer/CurveEditor/@Control@283287" method="_on_ControlPoint_gui_input"]
164+
[connection signal="mouse_entered" from="VBoxContainer/EditorContainer/CurveEditor/@Control@283287" to="VBoxContainer/EditorContainer/CurveEditor/@Control@283287" method="_on_mouse_entered"]
165+
[connection signal="mouse_exited" from="VBoxContainer/EditorContainer/CurveEditor/@Control@283287" to="VBoxContainer/EditorContainer/CurveEditor/@Control@283287" method="_on_mouse_exited"]
166+
[connection signal="value_changed" from="VBoxContainer/ControlUIContainer/ControlUI/PositionX" to="VBoxContainer/EditorContainer/CurveEditor" method="_on_position_x_value_changed"]
167+
[connection signal="value_changed" from="VBoxContainer/ControlUIContainer/ControlUI/PositionY" to="VBoxContainer/EditorContainer/CurveEditor" method="_on_position_y_value_changed"]
168+
[connection signal="value_changed" from="VBoxContainer/ControlUIContainer/ControlUI/LeftSlope" to="VBoxContainer/EditorContainer/CurveEditor" method="_on_left_slope_value_changed"]
169+
[connection signal="value_changed" from="VBoxContainer/ControlUIContainer/ControlUI/RightSlope" to="VBoxContainer/EditorContainer/CurveEditor" method="_on_right_slope_value_changed"]
67170
[connection signal="pressed" from="VBoxContainer/HBoxContainer/Invert" to="." method="_on_Invert_pressed"]
68171
[connection signal="pressed" from="VBoxContainer/HBoxContainer/OK" to="." method="_on_OK_pressed"]
69172
[connection signal="pressed" from="VBoxContainer/HBoxContainer/Cancel" to="." method="_on_Cancel_pressed"]

material_maker/widgets/curve_edit/curve_edit.gd

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,17 @@ var value = null: set = set_value
55

66
signal updated(curve, old_value)
77

8+
89
func _ready():
910
set_value(MMCurve.new())
1011

12+
1113
func set_value(v) -> void:
1214
value = v.duplicate()
1315
$CurveView.curve = value
1416
$CurveView.queue_redraw()
1517

18+
1619
func _on_CurveEdit_pressed():
1720
var dialog = preload("res://material_maker/widgets/curve_edit/curve_dialog.tscn").instantiate()
1821
var content_scale_factor = mm_globals.main_window.get_window().content_scale_factor
@@ -25,10 +28,12 @@ func _on_CurveEdit_pressed():
2528
set_value(new_curve.value)
2629
emit_signal("updated", new_curve.value.duplicate(), null if new_curve.value.compare(new_curve.previous_value) else new_curve.previous_value)
2730

31+
2832
func on_value_changed(v) -> void:
2933
set_value(v)
3034
emit_signal("updated", v.duplicate(), null)
3135

36+
3237
func _get_drag_data(_position) -> MMCurve:
3338
var duplicated_value = value.duplicate()
3439
var view = CurveView.new(duplicated_value)
@@ -39,9 +44,10 @@ func _get_drag_data(_position) -> MMCurve:
3944
set_drag_preview(button)
4045
return duplicated_value
4146

47+
4248
func _can_drop_data(_position, data) -> bool:
4349
return data is MMCurve
44-
50+
4551

4652
func _drop_data(_position, data) -> void:
4753
var old_curve : MMCurve = value

material_maker/widgets/curve_edit/curve_edit.tscn

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[gd_scene load_steps=3 format=3 uid="uid://cvv8rhglg3jlm"]
22

3-
[ext_resource type="Script" path="res://material_maker/widgets/curve_edit/curve_edit.gd" id="1"]
3+
[ext_resource type="Script" uid="uid://cd0ugv3swm5os" path="res://material_maker/widgets/curve_edit/curve_edit.gd" id="1"]
44
[ext_resource type="PackedScene" uid="uid://yeaj0tj7b08i" path="res://material_maker/widgets/curve_edit/curve_view.tscn" id="2"]
55

66
[node name="CurveEdit" type="Button"]
@@ -21,7 +21,5 @@ offset_left = 0.0
2121
offset_top = 0.0
2222
offset_right = 0.0
2323
offset_bottom = 0.0
24-
grow_horizontal = 2
25-
grow_vertical = 2
2624

2725
[connection signal="pressed" from="." to="." method="_on_CurveEdit_pressed"]

0 commit comments

Comments
 (0)