Skip to content

Commit

Permalink
Overhaul the path editor
Browse files Browse the repository at this point in the history
  • Loading branch information
MewPurPur committed Oct 23, 2023
1 parent f6f3bac commit 41a0058
Show file tree
Hide file tree
Showing 35 changed files with 1,345 additions and 598 deletions.
101 changes: 100 additions & 1 deletion project.godot
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,106 @@ duplicate={
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"command_or_control_autoremap":true,"alt_pressed":false,"shift_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"echo":false,"script":null)
]
}
move_relative={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":77,"key_label":0,"unicode":109,"echo":false,"script":null)
]
}
move_absolute={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":77,"key_label":0,"unicode":77,"echo":false,"script":null)
]
}
line_relative={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":76,"key_label":0,"unicode":108,"echo":false,"script":null)
]
}
line_absolute={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":76,"key_label":0,"unicode":76,"echo":false,"script":null)
]
}
horizontal_line_relative={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":72,"key_label":0,"unicode":104,"echo":false,"script":null)
]
}
horizontal_line_absolute={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":72,"key_label":0,"unicode":72,"echo":false,"script":null)
]
}
vertical_line_relative={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":86,"key_label":0,"unicode":118,"echo":false,"script":null)
]
}
vertical_line_absolute={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":86,"key_label":0,"unicode":86,"echo":false,"script":null)
]
}
close_path_relative={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":122,"echo":false,"script":null)
]
}
close_path_absolute={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":90,"echo":false,"script":null)
]
}
elliptical_arc_relative={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"echo":false,"script":null)
]
}
elliptical_arc_absolute={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":65,"echo":false,"script":null)
]
}
quadratic_bezier_relative={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":81,"key_label":0,"unicode":113,"echo":false,"script":null)
]
}
quadratic_bezier_absolute={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":81,"key_label":0,"unicode":81,"echo":false,"script":null)
]
}
shorthand_quadratic_bezier_relative={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":84,"key_label":0,"unicode":116,"echo":false,"script":null)
]
}
shorthand_quadratic_bezier_absolute={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":84,"key_label":0,"unicode":84,"echo":false,"script":null)
]
}
cubic_bezier_relative={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":67,"key_label":0,"unicode":99,"echo":false,"script":null)
]
}
cubic_bezier_absolute={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":67,"key_label":0,"unicode":67,"echo":false,"script":null)
]
}
shorthand_cubic_bezier_relative={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"echo":false,"script":null)
]
}
shorthand_cubic_bezier_absolute={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":67,"key_label":0,"unicode":67,"echo":false,"script":null)
]
}

[internationalization]

Expand All @@ -77,5 +177,4 @@ locale/translations=PackedStringArray("res://translations/translation_sheet.bg.t
[rendering]

environment/defaults/default_clear_color=Color(0.12, 0.132, 0.2, 1)
anti_aliasing/quality/msaa_2d=1
anti_aliasing/quality/screen_space_aa=1
100 changes: 96 additions & 4 deletions src/Interactions.gd
Original file line number Diff line number Diff line change
@@ -1,49 +1,119 @@
extends Node

const path_actions_dict := {
&"move_absolute": "M", &"move_relative": "m",
&"line_absolute": "L", &"line_relative": "l",
&"horizontal_line_absolute": "H", &"horizontal_line_relative": "h",
&"vertical_line_absolute": "V", &"vertical_line_relative": "v",
&"close_path_absolute": "Z", &"close_path_relative": "z",
&"elliptical_arc_absolute": "A", &"elliptical_arc_relative": "a",
&"cubic_bezier_absolute": "C", &"cubic_bezier_relative": "c",
&"shorthand_cubic_bezier_absolute": "S", &"shorthand_cubic_bezier_relative": "s",
&"quadratic_bezier_absolute": "Q", &"quadratic_bezier_relative": "q",
&"shorthand_quadratic_bezier_absolute": "T", &"shorthand_quadratic_bezier_relative": "t"
}

signal hover_changed
signal selection_changed

var hovered_tag := -1
var selected_tags: Array[int] = []

# For example, individual path commands.
var tag_with_inner_selections: int = -1
var inner_selections: Array[int] = []
var tag_with_inner_hovered: int = -1
var inner_hovered: int = -1


func _ready() -> void:
SVG.root_tag.tag_deleted.connect(_on_tag_deleted)
SVG.root_tag.tag_moved.connect(_on_tag_moved)
SVG.root_tag.child_tag_attribute_changed.connect(_on_child_tag_attribute_changed)

func toggle_selection(idx: int) -> void:
if idx >= 0:
var idx_idx := selected_tags.find(idx)
if idx_idx == -1:
selected_tags.append(idx)
selection_changed.emit()
else:
selected_tags.remove_at(idx_idx)
selection_changed.emit()
inner_selections.clear()
selection_changed.emit()

func toggle_inner_selection(idx: int, inner_idx: int) -> void:
if idx >= 0:
var idx_idx := inner_selections.find(inner_idx)
if idx_idx == -1:
inner_selections.append(inner_idx)
else:
inner_selections.remove_at(idx_idx)
selected_tags.clear()
selection_changed.emit()

func set_selection(idx: int) -> void:
if selected_tags.size() != 1 or selected_tags[0] != idx:
if tag_with_inner_selections != -1:
tag_with_inner_selections = -1
inner_selections.clear()
selected_tags = [idx]
selection_changed.emit()

func set_inner_selection(idx: int, inner_idx: int) -> void:
tag_with_inner_selections = idx
inner_selections = [inner_idx]
selected_tags.clear()
selection_changed.emit()

func clear_selection() -> void:
selected_tags.clear()
selection_changed.emit()

func clear_inner_selection() -> void:
inner_selections.clear()
tag_with_inner_selections = -1
selection_changed.emit()


func set_hovered(idx: int) -> void:
if hovered_tag != idx:
hovered_tag = idx
hover_changed.emit()

func set_inner_hovered(idx: int, inner_idx: int) -> void:
if tag_with_inner_hovered != idx:
tag_with_inner_hovered = idx
inner_hovered = inner_idx
if idx != -1 and inner_idx != -1:
hovered_tag = -1
hover_changed.emit()
elif inner_hovered != inner_idx:
inner_hovered = inner_idx
if idx != -1 and inner_idx != -1:
hovered_tag = -1
hover_changed.emit()

func remove_hovered(idx: int) -> void:
if hovered_tag == idx:
hovered_tag = -1
hover_changed.emit()

func remove_inner_hovered(idx: int, inner_idx: int) -> void:
if tag_with_inner_hovered == idx and inner_hovered == inner_idx:
tag_with_inner_hovered = -1
inner_hovered = -1
hover_changed.emit()

func clear_hovered() -> void:
if hovered_tag != -1:
hovered_tag = -1
hover_changed.emit()

func clear_inner_hovered() -> void:
if inner_hovered != -1:
inner_hovered = -1
hover_changed.emit()


func _on_tag_deleted(idx: int) -> void:
selected_tags.erase(idx)
Expand All @@ -60,11 +130,24 @@ func _on_tag_moved(old_idx: int, new_idx: int) -> void:
elif idx == old_idx:
selected_tags[i] = new_idx

func _on_child_tag_attribute_changed() -> void:
clear_inner_selection()


func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed(&"delete"):
for tag_idx in selected_tags:
SVG.root_tag.delete_tag(tag_idx)
if !selected_tags.is_empty():
selected_tags.sort()
selected_tags.reverse()
for tag_idx in selected_tags:
SVG.root_tag.delete_tag(tag_idx)
elif !inner_selections.is_empty() and tag_with_inner_selections != -1:
inner_selections.sort()
inner_selections.reverse()
for cmd_idx in inner_selections:
var tag_ref := SVG.root_tag.child_tags[tag_with_inner_selections]
match tag_ref.title:
"path": tag_ref.attributes.d.delete_command(cmd_idx)
elif event.is_action_pressed(&"move_up"):
var unaffected := 0
selected_tags.sort()
Expand All @@ -87,3 +170,12 @@ func _unhandled_input(event: InputEvent) -> void:
selected_tags.reverse()
for tag_idx in selected_tags:
SVG.root_tag.duplicate_tag(tag_idx)
else:
if !inner_selections.is_empty():
for action_name in path_actions_dict.keys():
if event.is_action_pressed(action_name):
var last_inner_selection = inner_selections.max()
var real_tag := SVG.root_tag.child_tags[tag_with_inner_selections]
real_tag.attributes.d.insert_command(
last_inner_selection + 1, path_actions_dict[action_name])
break
30 changes: 30 additions & 0 deletions src/Utils.gd
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,33 @@ static func vec_min(vec1: Vector2, vec2: Vector2) -> Vector2:

static func vec_max(vec1: Vector2, vec2: Vector2) -> Vector2:
return Vector2(maxf(vec1.x, vec2.x), maxf(vec1.y, vec2.y))

static func get_cubic_bezier_points(cp1: Vector2, cp2: Vector2,
cp3: Vector2, cp4: Vector2) -> PackedVector2Array:
var curve := Curve2D.new()
curve.add_point(cp1, Vector2(), cp2)
curve.add_point(cp4, cp3)
return curve.tessellate()

static func get_quadratic_bezier_points(cp1: Vector2, cp2: Vector2,
cp3: Vector2) -> PackedVector2Array:
var fcpo := 2/3.0 * (cp2 - cp1)
var fcpi := 2/3.0 * (cp2 - cp3)

var curve := Curve2D.new()
curve.add_point(cp1, Vector2(), fcpo)
curve.add_point(cp3, fcpi)
return curve.tessellate()

# Ellipse parametric equation.
static func E(c: Vector2, r: Vector2, cosine: float, sine: float, t: float) -> Vector2:
prints(sine, cosine)
var xt := r.x * cos(t)
var yt := r.y * sin(t)
return c + Vector2(xt * cosine - yt * sine, xt * sine + yt * cosine)

# Ellipse parametric equation derivative (for tangents).
static func Et(r: Vector2, cosine: float, sine: float, t: float) -> Vector2:
var xt := -r.x * sin(t)
var yt := r.y * cos(t)
return Vector2(xt * cosine - yt * sine, xt * sine + yt * cosine)
7 changes: 7 additions & 0 deletions src/data_classes/AttributePath.gd
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ func add_command(command_char: String) -> void:
locate_start_points()
command_changed.emit()

func insert_command(idx: int, command_char: String) -> void:
commands.insert(idx, PathCommand.translation_dict[command_char.to_upper()].new())
if Utils.is_string_lower(command_char):
commands[idx].toggle_relative()
locate_start_points()
command_changed.emit()

func delete_command(idx: int) -> void:
commands.remove_at(idx)
locate_start_points()
Expand Down
4 changes: 2 additions & 2 deletions src/small_editors/context_popup.gd
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ should_reset_size := true) -> void:

func set_btn_array(buttons: Array[Button]) -> void:
for button in main_container.get_children():
button.queue_free()
button.free()
if buttons.is_empty():
return
elif buttons.size() == 1:
add_button(buttons[0], true, true)
return
else:
add_button(buttons.pop_front(), true, false)
add_button(buttons.pop_front(), true, false, false)
for i in buttons.size() - 1:
add_button(buttons.pop_front(), false, false, false)
add_button(buttons[0], false, true)
Expand Down
7 changes: 4 additions & 3 deletions src/small_editors/flag_field.gd
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ func _draw() -> void:
if hovered:
var hover_stylebox := StyleBoxFlat.new()
hover_stylebox.draw_center = false
hover_stylebox.set_corner_radius_all(5)
hover_stylebox.set_border_width_all(2)
hover_stylebox.border_color = Color(1, 1, 1, 0.15)
hover_stylebox.corner_radius_top_left = 3
hover_stylebox.corner_radius_top_right = 3
hover_stylebox.border_width_bottom = 2
hover_stylebox.border_color = Color(1, 1, 1, 0.2)
draw_style_box(hover_stylebox, Rect2(Vector2.ZERO, size))
28 changes: 8 additions & 20 deletions src/small_editors/flag_field.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,26 @@
[ext_resource type="Script" path="res://src/small_editors/flag_field.gd" id="2_0bhg4"]

[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_oo47u"]
content_margin_left = 6.0
content_margin_left = 5.0
content_margin_top = 0.0
content_margin_right = 6.0
content_margin_right = 5.0
content_margin_bottom = 0.0
bg_color = Color(0.4, 0.121569, 0.121569, 1)
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_color = Color(0.85098, 0.168627, 0.168627, 1)
corner_radius_top_left = 5
corner_radius_top_right = 5
corner_radius_bottom_right = 5
corner_radius_bottom_left = 5
corner_detail = 16
corner_radius_top_left = 3
corner_radius_top_right = 3

[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_uepoa"]
content_margin_left = 6.0
content_margin_left = 5.0
content_margin_top = 0.0
content_margin_right = 6.0
content_margin_right = 5.0
content_margin_bottom = 0.0
bg_color = Color(0.12, 0.4, 0.12, 1)
border_width_left = 2
border_width_top = 2
border_width_right = 2
border_width_bottom = 2
border_color = Color(0.4675, 0.85, 0.085, 1)
corner_radius_top_left = 5
corner_radius_top_right = 5
corner_radius_bottom_right = 5
corner_radius_bottom_left = 5
corner_detail = 16
corner_radius_top_left = 3
corner_radius_top_right = 3

[node name="FlagField" type="Button"]
offset_right = 13.0
Expand Down

0 comments on commit 41a0058

Please sign in to comment.