Skip to content

Commit

Permalink
Add native global menu support (#644)
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronfranke authored Jul 23, 2024
1 parent 2517209 commit 178b45e
Show file tree
Hide file tree
Showing 15 changed files with 547 additions and 146 deletions.
8 changes: 7 additions & 1 deletion project.godot
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ SVG="*res://src/SVG.gd"
Indications="*res://src/Indications.gd"
HandlerGUI="*res://src/HandlerGUI.gd"

[debug]

gdscript/warnings/int_as_enum_without_cast=0
gdscript/warnings/int_as_enum_without_match=0

[display]

window/size/viewport_width=1024
Expand Down Expand Up @@ -309,7 +314,8 @@ view_overlay_reference={
}
find={
"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":true,"meta_pressed":false,"pressed":false,"keycode":70,"physical_keycode":0,"key_label":0,"unicode":102,"location":0,"echo":false,"script":null)
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":true,"meta_pressed":false,"pressed":false,"keycode":70,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
, 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":true,"pressed":false,"keycode":70,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}

Expand Down
4 changes: 4 additions & 0 deletions src/GlobalSettings.gd
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# This singleton handles session data and settings.
extends Node


signal keybinds_changed

# Session data
var save_data := SaveData.new()
const save_path = "user://save.tres"
Expand Down Expand Up @@ -228,6 +231,7 @@ func save_palettes() -> void:
func save_keybind(action: String) -> void:
config.set_value("keybinds", action, InputMap.action_get_events(action))
config.save(config_path)
keybinds_changed.emit()


func modify_save_data(property: String, new_value: Variant) -> void:
Expand Down
8 changes: 5 additions & 3 deletions src/TranslationUtils.gd
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ class_name TranslationUtils extends RefCounted

static func get_shortcut_description(action_name: String) -> String:
match action_name:
"export": return TranslationServer.translate("Export")
"import": return TranslationServer.translate("Import")
"save": return TranslationServer.translate("Save SVG")
"export": return TranslationServer.translate("Export Image")
"import": return TranslationServer.translate("Import SVG")
"save": return TranslationServer.translate("Export SVG")
"optimize": return TranslationServer.translate("Optimize")
"copy_svg_text": return TranslationServer.translate("Copy all text")
"reset_svg": return TranslationServer.translate("Reset SVG")
Expand All @@ -17,12 +17,14 @@ static func get_shortcut_description(action_name: String) -> String:
"delete": return TranslationServer.translate("Delete the selection")
"move_up": return TranslationServer.translate("Move the selected elements up")
"move_down": return TranslationServer.translate("Move the selected elements down")
"find": return TranslationServer.translate("Find")
"zoom_in": return TranslationServer.translate("Zoom in")
"zoom_out": return TranslationServer.translate("Zoom out")
"zoom_reset": return TranslationServer.translate("Zoom reset")
"view_show_grid": return TranslationServer.translate("Show grid")
"view_show_handles": return TranslationServer.translate("Show handles")
"view_rasterized_svg": return TranslationServer.translate("Show rasterized SVG")
"snap_toggle": return TranslationServer.translate("Enable snap")
"load_reference": return TranslationServer.translate("Load reference image")
"view_show_reference": return TranslationServer.translate("Show reference image")
"view_overlay_reference": return TranslationServer.translate("Overlay reference image")
Expand Down
223 changes: 223 additions & 0 deletions src/ui_parts/global_menu.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
extends Node


var global_rid: RID
var appl_rid: RID
var help_rid: RID

var file_rid: RID
var file_index: int
var file_clear_svg_index: int
var file_optimize_index: int
var file_clear_assoc_index: int
var file_reset_svg_index: int

var edit_rid: RID
var edit_index: int
var tool_rid: RID
var tool_index: int

var view_rid: RID
var view_index: int
var view_show_grid_index: int
var view_show_handles_index: int
var view_rasterized_svg_index: int

var snap_rid: RID
var snap_index: int
var snap_enable_index: int
var snap_0125_index: int
var snap_025_index: int
var snap_05_index: int
var snap_1_index: int
var snap_2_index: int
var snap_4_index: int


func _enter_tree() -> void:
if not DisplayServer.has_feature(DisplayServer.FEATURE_GLOBAL_MENU):
queue_free()
return
# Included menus.
global_rid = NativeMenu.get_system_menu(NativeMenu.MAIN_MENU_ID)
appl_rid = NativeMenu.get_system_menu(NativeMenu.APPLICATION_MENU_ID)
help_rid = NativeMenu.get_system_menu(NativeMenu.HELP_MENU_ID)
# Custom menus.
_generate_main_menus()
_setup_menu_items()
GlobalSettings.keybinds_changed.connect(_reset_menu_items)
SVG.text_changed.connect(_on_svg_text_changed)


func _notification(what: int) -> void:
if what == Utils.CustomNotification.LANGUAGE_CHANGED:
_clear_menu_items()
NativeMenu.remove_item(global_rid, snap_index)
NativeMenu.remove_item(global_rid, view_index)
NativeMenu.remove_item(global_rid, tool_index)
NativeMenu.remove_item(global_rid, edit_index)
NativeMenu.remove_item(global_rid, file_index)
NativeMenu.free_menu(file_rid)
NativeMenu.free_menu(edit_rid)
NativeMenu.free_menu(tool_rid)
NativeMenu.free_menu(view_rid)
NativeMenu.free_menu(snap_rid)
_generate_main_menus()
_setup_menu_items()


func _generate_main_menus() -> void:
file_rid = NativeMenu.create_menu()
edit_rid = NativeMenu.create_menu()
tool_rid = NativeMenu.create_menu()
view_rid = NativeMenu.create_menu()
snap_rid = NativeMenu.create_menu()
file_index = NativeMenu.add_submenu_item(global_rid, TranslationServer.translate("File"), file_rid)
edit_index = NativeMenu.add_submenu_item(global_rid, TranslationServer.translate("Edit"), edit_rid)
tool_index = NativeMenu.add_submenu_item(global_rid, TranslationServer.translate("Tool"), tool_rid)
view_index = NativeMenu.add_submenu_item(global_rid, TranslationServer.translate("View"), view_rid)
snap_index = NativeMenu.add_submenu_item(global_rid, TranslationServer.translate("Snap"), snap_rid)


func _reset_menu_items() -> void:
_setup_menu_items()


func _clear_menu_items() -> void:
NativeMenu.clear(appl_rid)
NativeMenu.clear(help_rid)
NativeMenu.clear(file_rid)
NativeMenu.clear(edit_rid)
NativeMenu.clear(tool_rid)
NativeMenu.clear(view_rid)
NativeMenu.clear(snap_rid)


func _setup_menu_items() -> void:
# Included App and Help menus.
_add_action(appl_rid, "open_settings")
_add_icon_item(help_rid, "open_settings", load("res://visual/icons/Gear.svg"))
_add_icon_item(help_rid, "about_repo", load("res://visual/icons/Link.svg"))
_add_icon_item(help_rid, "about_info", load("res://visual/icon.svg"))
_add_icon_item(help_rid, "about_donate", load("res://visual/icons/Heart.svg"))
_add_icon_item(help_rid, "about_website", load("res://visual/icons/Link.svg"))
_add_icon_item(help_rid, "check_updates", load("res://visual/icons/Reload.svg"))
# File menu.
_add_action(file_rid, "import")
_add_action(file_rid, "export")
_add_action(file_rid, "save")
NativeMenu.add_separator(file_rid)
_add_action(file_rid, "copy_svg_text")
file_clear_svg_index = _add_action(file_rid, "clear_svg")
file_optimize_index = _add_action(file_rid, "optimize")
NativeMenu.add_separator(file_rid)
file_clear_assoc_index = _add_action(file_rid, "clear_file_path")
file_reset_svg_index = _add_action(file_rid, "reset_svg")
_on_svg_text_changed()
# Edit and Tool menus.
_add_many_actions(edit_rid, GlobalSettings.keybinds_dict["edit"].keys())
_add_many_actions(tool_rid, GlobalSettings.keybinds_dict["tool"].keys())
# View menu.
view_show_grid_index = _add_check_item(view_rid, "view_show_grid")
view_show_handles_index = _add_check_item(view_rid, "view_show_handles")
view_rasterized_svg_index = _add_check_item(view_rid, "view_rasterized_svg")
_on_display_view_settings_updated(true, true, false)
NativeMenu.add_separator(view_rid)
_add_action(view_rid, "zoom_in")
_add_action(view_rid, "zoom_out")
_add_action(view_rid, "zoom_reset")
# Snap menu.
snap_enable_index = _add_check_item(snap_rid, "snap_toggle")
NativeMenu.add_separator(snap_rid)
snap_0125_index = NativeMenu.add_radio_check_item(snap_rid, "0.125", _set_snap, _set_snap, 0.125)
snap_025_index = NativeMenu.add_radio_check_item(snap_rid, "0.25", _set_snap, _set_snap, 0.25)
snap_05_index = NativeMenu.add_radio_check_item(snap_rid, "0.5", _set_snap, _set_snap, 0.5)
snap_1_index = NativeMenu.add_radio_check_item(snap_rid, "1", _set_snap, _set_snap, 1)
snap_2_index = NativeMenu.add_radio_check_item(snap_rid, "2", _set_snap, _set_snap, 2)
snap_4_index = NativeMenu.add_radio_check_item(snap_rid, "4", _set_snap, _set_snap, 4)


func _add_many_actions(menu_rid: RID, actions: Array) -> void:
for action in actions:
_add_action(menu_rid, action)


func _add_action(menu_rid: RID, action_name: StringName) -> int:
var display_name = _get_action_display_name(action_name)
var key = _get_keycode_for_events(InputMap.action_get_events(action_name))
return NativeMenu.add_item(menu_rid, display_name, _action_call, _action_call, action_name, key)


func _add_check_item(menu_rid: RID, action_name: StringName) -> int:
var display_name = _get_action_display_name(action_name)
return NativeMenu.add_check_item(menu_rid, display_name, _action_call, _action_call, action_name)


func _add_icon_item(menu_rid: RID, action_name: StringName, icon: Texture2D) -> int:
var display_name = _get_action_display_name(action_name)
return NativeMenu.add_icon_item(menu_rid, icon, display_name, _action_call, _action_call, action_name)


func _get_action_display_name(action_name: StringName) -> String:
var display_name = TranslationUtils.get_shortcut_description(action_name)
if display_name.is_empty():
display_name = action_name.capitalize().replace("Svg", "SVG")
return display_name


func _get_keycode_for_events(input_events: Array[InputEvent]) -> Key:
for input_event in input_events:
if input_event is InputEventKey:
var key = input_event.get_keycode_with_modifiers()
if key != KEY_NONE:
return key
key = input_event.get_physical_keycode_with_modifiers()
if key != KEY_NONE:
return key
return KEY_NONE


func _on_svg_text_changed() -> void:
NativeMenu.set_item_disabled(file_rid, file_clear_svg_index, SVG.text == SVG.DEFAULT)
var empty_path: bool = GlobalSettings.save_data.current_file_path.is_empty()
NativeMenu.set_item_disabled(file_rid, file_clear_assoc_index, empty_path)
NativeMenu.set_item_disabled(file_rid, file_reset_svg_index, empty_path)


func _on_display_view_settings_updated(show_grid: bool, show_handles: bool, rasterized_svg: bool) -> void:
NativeMenu.set_item_checked(view_rid, view_show_grid_index, show_grid)
NativeMenu.set_item_checked(view_rid, view_show_handles_index, show_handles)
NativeMenu.set_item_checked(view_rid, view_rasterized_svg_index, rasterized_svg)


func _on_display_snap_settings_updated(snap_enabled: bool, snap_amount: float) -> void:
NativeMenu.set_item_checked(snap_rid, snap_enable_index, snap_enabled)
NativeMenu.set_item_checked(snap_rid, snap_0125_index, false)
NativeMenu.set_item_checked(snap_rid, snap_025_index, false)
NativeMenu.set_item_checked(snap_rid, snap_05_index, false)
NativeMenu.set_item_checked(snap_rid, snap_1_index, false)
NativeMenu.set_item_checked(snap_rid, snap_2_index, false)
NativeMenu.set_item_checked(snap_rid, snap_4_index, false)
if is_equal_approx(snap_amount, 0.125):
NativeMenu.set_item_checked(snap_rid, snap_0125_index, true)
elif is_equal_approx(snap_amount, 0.25):
NativeMenu.set_item_checked(snap_rid, snap_025_index, true)
elif is_equal_approx(snap_amount, 0.5):
NativeMenu.set_item_checked(snap_rid, snap_05_index, true)
elif is_equal_approx(snap_amount, 1):
NativeMenu.set_item_checked(snap_rid, snap_1_index, true)
elif is_equal_approx(snap_amount, 2):
NativeMenu.set_item_checked(snap_rid, snap_2_index, true)
elif is_equal_approx(snap_amount, 4):
NativeMenu.set_item_checked(snap_rid, snap_4_index, true)


func _set_snap(tag: float) -> void:
%Display.set_snap_amount(tag)


func _action_call(tag: StringName) -> void:
var a = InputEventAction.new()
a.action = tag
a.pressed = true
Input.parse_input_event(a)
9 changes: 8 additions & 1 deletion src/ui_parts/main_scene.tscn
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
[gd_scene load_steps=6 format=3 uid="uid://ce6j54x27pom"]
[gd_scene load_steps=7 format=3 uid="uid://ce6j54x27pom"]

[ext_resource type="PackedScene" uid="uid://cr1fdlmbknnko" path="res://src/ui_parts/code_editor.tscn" id="1_0jgh3"]
[ext_resource type="Texture2D" uid="uid://co75w07yqmcro" path="res://visual/icons/theme/SplitGrabber2.svg" id="1_7y812"]
[ext_resource type="PackedScene" uid="uid://ccynisiuyn5qn" path="res://src/ui_parts/inspector.tscn" id="1_afxvd"]
[ext_resource type="Script" path="res://src/ui_parts/main_scene.gd" id="1_c0fkj"]
[ext_resource type="PackedScene" uid="uid://bvrncl7e6yn5b" path="res://src/ui_parts/display.tscn" id="3_qbqbs"]
[ext_resource type="Script" path="res://src/ui_parts/global_menu.gd" id="5_wda5e"]

[node name="MainScene" type="HBoxContainer"]
anchors_preset = 15
Expand Down Expand Up @@ -42,3 +43,9 @@ layout_mode = 2
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3

[node name="GlobalMenu" type="Node" parent="."]
script = ExtResource("5_wda5e")

[connection signal="snap_settings_updated" from="HSplitContainer/Display" to="GlobalMenu" method="_on_display_snap_settings_updated"]
[connection signal="view_settings_updated" from="HSplitContainer/Display" to="GlobalMenu" method="_on_display_view_settings_updated"]
Loading

0 comments on commit 178b45e

Please sign in to comment.