diff --git a/addons/ply/gui/inspector/inspector.tscn b/addons/ply/gui/inspector/inspector.tscn index 15bbc44..13f3db4 100644 --- a/addons/ply/gui/inspector/inspector.tscn +++ b/addons/ply/gui/inspector/inspector.tscn @@ -6,198 +6,132 @@ anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 +offset_right = -1648.0 +grow_horizontal = 2 +grow_vertical = 2 size_flags_horizontal = 3 size_flags_vertical = 3 script = ExtResource("1") [node name="G" type="GridContainer" parent="."] layout_mode = 2 -offset_right = 1152.0 -offset_bottom = 86.0 columns = 2 [node name="Translate" type="Label" parent="G"] layout_mode = 2 -offset_right = 73.0 -offset_bottom = 26.0 text = "Translate" [node name="TranslateInputs" type="HBoxContainer" parent="G"] layout_mode = 2 -offset_left = 77.0 -offset_right = 1152.0 -offset_bottom = 26.0 size_flags_horizontal = 3 [node name="Rotate" type="Label" parent="G"] layout_mode = 2 -offset_top = 30.0 -offset_right = 73.0 -offset_bottom = 56.0 text = "Rotate" [node name="RotateInputs" type="HBoxContainer" parent="G"] layout_mode = 2 -offset_left = 77.0 -offset_top = 30.0 -offset_right = 1152.0 -offset_bottom = 56.0 size_flags_horizontal = 3 [node name="Scale" type="Label" parent="G"] layout_mode = 2 -offset_top = 60.0 -offset_right = 73.0 -offset_bottom = 86.0 text = "Scale" [node name="ScaleInputs" type="HBoxContainer" parent="G"] layout_mode = 2 -offset_left = 77.0 -offset_top = 60.0 -offset_right = 1152.0 -offset_bottom = 86.0 size_flags_horizontal = 3 [node name="V" type="GridContainer" parent="."] layout_mode = 2 -offset_top = 90.0 -offset_right = 1152.0 -offset_bottom = 226.0 columns = 2 [node name="Label" type="Label" parent="V"] layout_mode = 2 -offset_top = 2.0 -offset_right = 71.0 -offset_bottom = 28.0 text = "Vertices " [node name="VertexCount" type="LineEdit" parent="V"] layout_mode = 2 -offset_left = 75.0 -offset_right = 1152.0 -offset_bottom = 31.0 size_flags_horizontal = 3 editable = false [node name="Label2" type="Label" parent="V"] layout_mode = 2 -offset_top = 37.0 -offset_right = 71.0 -offset_bottom = 63.0 text = "Edges" [node name="EdgeCount" type="LineEdit" parent="V"] layout_mode = 2 -offset_left = 75.0 -offset_top = 35.0 -offset_right = 1152.0 -offset_bottom = 66.0 size_flags_horizontal = 3 editable = false [node name="Label3" type="Label" parent="V"] layout_mode = 2 -offset_top = 72.0 -offset_right = 71.0 -offset_bottom = 98.0 text = "Faces" [node name="FaceCount" type="LineEdit" parent="V"] layout_mode = 2 -offset_left = 75.0 -offset_top = 70.0 -offset_right = 1152.0 -offset_bottom = 101.0 size_flags_horizontal = 3 editable = false [node name="Label4" type="Label" parent="V"] layout_mode = 2 -offset_top = 107.0 -offset_right = 71.0 -offset_bottom = 133.0 text = "Selection" [node name="Selection" type="LineEdit" parent="V"] layout_mode = 2 -offset_left = 75.0 -offset_top = 105.0 -offset_right = 1152.0 -offset_bottom = 136.0 size_flags_horizontal = 3 editable = false [node name="HSeparator" type="HSeparator" parent="."] layout_mode = 2 -offset_top = 230.0 -offset_right = 1152.0 -offset_bottom = 234.0 [node name="SnapValuesTitle" type="Label" parent="."] layout_mode = 2 -offset_top = 238.0 -offset_right = 1152.0 -offset_bottom = 264.0 text = "Gizmo Snap Values" -[node name="P" type="GridContainer" parent="."] +[node name="P" type="HBoxContainer" parent="."] layout_mode = 2 -offset_top = 268.0 -offset_right = 1152.0 -offset_bottom = 299.0 -columns = 6 - -[node name="Translate" type="Label" parent="P"] -layout_mode = 2 -offset_top = 2.0 -offset_right = 73.0 -offset_bottom = 28.0 -text = "Translate" [node name="TranslateSnap" type="SpinBox" parent="P"] layout_mode = 2 -offset_left = 77.0 -offset_right = 386.0 -offset_bottom = 31.0 size_flags_horizontal = 3 min_value = 0.01 max_value = 50000.0 step = 0.001 value = 1.0 -[node name="Rotate" type="Label" parent="P"] -layout_mode = 2 -offset_left = 390.0 -offset_top = 2.0 -offset_right = 484.0 -offset_bottom = 28.0 -text = "Rotate (deg)" - [node name="RotateSnap" type="SpinBox" parent="P"] layout_mode = 2 -offset_left = 488.0 -offset_right = 796.0 -offset_bottom = 31.0 size_flags_horizontal = 3 max_value = 360.0 step = 0.001 value = 15.0 -[node name="Scale" type="Label" parent="P"] -layout_mode = 2 -offset_left = 800.0 -offset_top = 2.0 -offset_right = 840.0 -offset_bottom = 28.0 -text = "Scale" - [node name="ScaleSnap" type="SpinBox" parent="P"] layout_mode = 2 -offset_left = 844.0 -offset_right = 1152.0 -offset_bottom = 31.0 size_flags_horizontal = 3 step = 0.001 value = 0.1 + +[node name="P2" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="Translate" type="Label" parent="P2"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "Translate" +horizontal_alignment = 1 +justification_flags = 171 + +[node name="Rotate" type="Label" parent="P2"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "Rotate (deg)" +horizontal_alignment = 1 +justification_flags = 171 + +[node name="Scale" type="Label" parent="P2"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "Scale" +horizontal_alignment = 1 +justification_flags = 171 diff --git a/addons/ply/gui/toolbar/toolbar.gd b/addons/ply/gui/toolbar/toolbar.gd index 1db560a..a2b140e 100644 --- a/addons/ply/gui/toolbar/toolbar.gd +++ b/addons/ply/gui/toolbar/toolbar.gd @@ -22,10 +22,13 @@ const Import = preload("res://addons/ply/tools/import.gd") var plugin: EditorPlugin +@onready var content_vbox = $Scroll/Content @onready var selection_mesh = $Scroll/Content/Mesh @onready var selection_face = $Scroll/Content/Face @onready var selection_edge = $Scroll/Content/Edge @onready var selection_vertex = $Scroll/Content/Vertex +@onready var select_all = $Scroll/Content/ToolModeLabel/MarginContainer/SelectAll +@onready var snap_checkbox = $Scroll/Content/SnapCheckbox @onready var gizmo_global = $Scroll/Content/Global @onready var gizmo_local = $Scroll/Content/Local @@ -48,15 +51,9 @@ var plugin: EditorPlugin @onready var face_subdivide = $Scroll/Content/FaceTools/Subdivide @onready var face_triangulate = $Scroll/Content/FaceTools/Triangulate -@onready var face_set_shape_1 = $"Scroll/Content/FaceTools/Surfaces/1" -@onready var face_set_shape_2 = $"Scroll/Content/FaceTools/Surfaces/2" -@onready var face_set_shape_3 = $"Scroll/Content/FaceTools/Surfaces/3" -@onready var face_set_shape_4 = $"Scroll/Content/FaceTools/Surfaces/4" -@onready var face_set_shape_5 = $"Scroll/Content/FaceTools/Surfaces/5" -@onready var face_set_shape_6 = $"Scroll/Content/FaceTools/Surfaces/6" -@onready var face_set_shape_7 = $"Scroll/Content/FaceTools/Surfaces/7" -@onready var face_set_shape_8 = $"Scroll/Content/FaceTools/Surfaces/8" -@onready var face_set_shape_9 = $"Scroll/Content/FaceTools/Surfaces/9" +@onready var zero_face_button = $'Scroll/Content/FaceTools/PaintSurfaces/MarginContainer/HboxContainer/0' +@onready var face_set_surfaces = $"Scroll/Content/FaceTools/Surfaces" +@onready var expand_surfaces_button = $"Scroll/Content/FaceTools/ExpandSurfaces" @onready var face_color_picker = $Scroll/Content/FaceTools/VertexColorPicker @onready var edge_tools = $Scroll/Content/EdgeTools @@ -68,6 +65,12 @@ var plugin: EditorPlugin @onready var vertex_tools = $Scroll/Content/VertexTools @onready var vertex_color_picker = $Scroll/Content/VertexTools/VertexColorPicker + +var replacing_surface_idx_button: Button = null +var replacing_surface_label: Label = null +var hovered_button: Button = null + + func _ready() -> void: var config = ConfigFile.new() var err = config.load("res://addons/ply/plugin.cfg") @@ -79,6 +82,10 @@ func _ready() -> void: selection_face.toggled.connect(_update_selection_mode.bind(SelectionMode.FACE)) selection_edge.toggled.connect(_update_selection_mode.bind(SelectionMode.EDGE)) selection_vertex.toggled.connect(_update_selection_mode.bind(SelectionMode.VERTEX)) + + + select_all.pressed.connect(_select_all) + snap_checkbox.toggled.connect(_on_snap_checkbox_toggle) gizmo_global.toggled.connect(_update_gizmo_mode.bind(GizmoMode.GLOBAL)) gizmo_local.toggled.connect(_update_gizmo_mode.bind(GizmoMode.LOCAL)) @@ -96,18 +103,60 @@ func _ready() -> void: face_color_picker.pressed.connect(_on_face_color_pressed) face_color_picker.popup_closed.connect(_on_face_color_closed) - face_set_shape_1.pressed.connect(_set_face_surface.bind(0)) - face_set_shape_2.pressed.connect(_set_face_surface.bind(1)) - face_set_shape_3.pressed.connect(_set_face_surface.bind(2)) - face_set_shape_4.pressed.connect(_set_face_surface.bind(3)) - face_set_shape_5.pressed.connect(_set_face_surface.bind(4)) - face_set_shape_6.pressed.connect(_set_face_surface.bind(5)) - face_set_shape_7.pressed.connect(_set_face_surface.bind(6)) - face_set_shape_8.pressed.connect(_set_face_surface.bind(7)) - face_set_shape_9.pressed.connect(_set_face_surface.bind(8)) - + for v: Button in (face_set_surfaces.get_children() + [zero_face_button]): + v.pressed.connect(func() -> void: + if replacing_surface_idx_button != null: + _set_face_surface(v.name.to_int(), replacing_surface_idx_button.get_meta('faces', [])) + replacing_surface_idx_button = null + hovered_button = null + _on_geometry_selection_changed() + return + + for v2: Button in face_set_surfaces.get_children(): + if v2 != v: + v2.set_pressed_no_signal(false) + + _set_face_surface(v.name.to_int()) + ) + var unpress := func() -> void: + _set_face_surface(0, v.get_meta('faces', [])) + v.set_pressed_no_signal(false) + + v.mouse_entered.connect(func() -> void: + if replacing_surface_idx_button != null: + hovered_button = v + if Input.is_mouse_button_pressed(MOUSE_BUTTON_RIGHT): #erase + unpress.call() + ) + v.mouse_exited.connect(func() -> void: + if replacing_surface_idx_button != null: hovered_button = null + ) + + v.gui_input.connect(func(event: InputEvent) -> void: + if (event is InputEventMouseButton) and event.pressed: + match event.button_index: + MOUSE_BUTTON_RIGHT: + unpress.call() + + MOUSE_BUTTON_MIDDLE: + hovered_button = v + replacing_surface_idx_button = v + ) + + + + + expand_surfaces_button.pressed.connect(func() -> void: + for v: Button in face_set_surfaces.get_children(): + if v.name.to_int() > 9: + v.visible = expand_surfaces_button.button_pressed + expand_surfaces_button.text = ('Less' if expand_surfaces_button.button_pressed else 'More') + ) + + face_select_loop_1.pressed.connect(_face_select_loop.bind(0)) face_select_loop_2.pressed.connect(_face_select_loop.bind(1)) + face_extrude.pressed.connect(_face_extrude) face_connect.pressed.connect(_face_connect) face_subdivide.pressed.connect(_face_subdivide) @@ -123,32 +172,62 @@ func _ready() -> void: vertex_color_picker.popup_closed.connect(_on_face_color_closed) if plugin: + snap_checkbox.set_pressed_no_signal(plugin.current_settings.snap) #bool plugin.selection_changed.connect(_on_selection_changed) + + + var selected_mesh func _on_selection_changed(selection): - if selected_mesh and selected_mesh.has_signal("selection_changed"): + if selected_mesh and is_instance_valid(selected_mesh) and selected_mesh.has_signal("selection_changed"): selected_mesh.selection_changed.disconnect(_on_geometry_selection_changed) selected_mesh = selection - if selected_mesh and selected_mesh.has_signal("selection_changed"): + if selected_mesh and is_instance_valid(selected_mesh) and selected_mesh.has_signal("selection_changed"): selected_mesh.selection_changed.connect(_on_geometry_selection_changed) + func _on_geometry_selection_changed(): match selection_mode: SelectionMode.FACE: - var color - var many = false - for f_idx in selected_mesh.selected_faces: + var color: Variant = null #Color? + var surface_ids: Dictionary = {} #Dictionary[int, Array[int]] + var many_different_colors = false + + replacing_surface_idx_button = null + + for f_idx: int in selected_mesh.selected_faces: var f_color = selected_mesh.ply_mesh.get_face_color(f_idx) + var surface_id: int = selected_mesh.ply_mesh.face_surfaces[f_idx] if (selected_mesh.ply_mesh.face_surfaces.size() - 1) >= f_idx else 0 + if color == null: color = f_color - if !color.is_equal_approx(f_color): - many = true - + + + if !surface_ids.has(surface_id): + surface_ids[surface_id] = [] + surface_ids[surface_id].append(f_idx) + + if color != null and !color.is_equal_approx(f_color): + many_different_colors = true + if color == null: color = Color.WHITE - if many: + + var surface_ids_count := surface_ids.size() + for v: Button in (face_set_surfaces.get_children() + [zero_face_button]): + if v.has_meta('faces'): v.remove_meta('faces') + + if surface_ids_count <= 0: + v.set_pressed_no_signal(v.name.to_int() == surface_ids.keys()[0] if surface_ids_count > 0 else false) + else: + v.set_pressed_no_signal(surface_ids.has(v.name.to_int())) + if v.button_pressed: + v.set_meta('faces', surface_ids[v.name.to_int()] as Array[int]) + + + if many_different_colors: face_color_picker.color = Color.WHITE face_color_picker.get_node("Label").visible = true else: @@ -178,6 +257,35 @@ func _on_geometry_selection_changed(): func _process(_delta) -> void: _update_tool_visibility() + + if replacing_surface_idx_button != null: + if !replacing_surface_label: + replacing_surface_label = Label.new() + replacing_surface_label.top_level = true + replacing_surface_label.name = '_replacing_surface_label' + add_child(replacing_surface_label) + + + replacing_surface_label.text = ('Replace %s -> %s (%s faces)' % [ + replacing_surface_idx_button.name, + (hovered_button.name if hovered_button != null else '?'), + (str(replacing_surface_idx_button.get_meta('faces').size()) if replacing_surface_idx_button.has_meta('faces') else '?'), #Array | String + ]) + replacing_surface_label.global_position = get_global_mouse_position() + + if !hovered_button: + if Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT): + if replacing_surface_label != null: + remove_child(replacing_surface_label) + replacing_surface_label.queue_free() + replacing_surface_label = null + replacing_surface_idx_button = null + hovered_button = null + else: + if replacing_surface_label != null: + remove_child(replacing_surface_label) + replacing_surface_label.queue_free() + replacing_surface_label = null var selection_mode: int = SelectionMode.MESH @@ -185,6 +293,10 @@ var selection_mode: int = SelectionMode.MESH func _update_selection_mode(selected, mode) -> void: if selected: + var selection_button: Button = content_vbox.get_child(1 + mode) + if selection_button != null: + select_all.icon = selection_button.icon + selection_mode = mode emit_signal("selection_mode_changed", mode) @@ -206,15 +318,25 @@ func _update_tool_visibility() -> void: func set_selection_mode(mode) -> void: + var selection_button: Button = null match mode: SelectionMode.MESH: selection_mesh.pressed = true + selection_button = selection_mesh SelectionMode.FACE: selection_face.pressed = true + selection_button = selection_face SelectionMode.EDGE: selection_edge.pressed = true + selection_button = selection_edge SelectionMode.VERTEX: selection_vertex.pressed = true + selection_button = selection_vertex + + print(selection_button) + if selection_button != null: + select_all.icon = selection_button.icon + print(selection_button.icon, select_all) func _open_generators_modal(): @@ -386,6 +508,27 @@ func _face_connect(): plugin.get_undo_redo() ) +func _select_all(): + if plugin.ignore_inputs: + return + if ( + not plugin.selection + ): + return + + + if selection_mode == SelectionMode.MESH: + _update_selection_mode(true, SelectionMode.FACE) + + match selection_mode: + SelectionMode.VERTEX: plugin.selection.selected_vertices = range(plugin.selection.ply_mesh.vertexes.size()) + SelectionMode.EDGE: plugin.selection.selected_edges = Array(plugin.selection.ply_mesh.vertex_edges) + SelectionMode.FACE: plugin.selection.selected_faces = Array(plugin.selection.ply_mesh.edge_faces) + + if selected_mesh != null and is_instance_valid(selected_mesh): + selected_mesh.selection_changed.emit() + + func _face_subdivide(): if plugin.ignore_inputs: @@ -407,7 +550,7 @@ func _face_triangulate(): plugin.selection.ply_mesh.commit_edit("Triangulate Faces", plugin.get_undo_redo(), pre_edit) -func _set_face_surface(s): +func _set_face_surface(s: int, for_faces: Array = []): #Array[int] if plugin.ignore_inputs: return if ( @@ -417,8 +560,10 @@ func _set_face_surface(s): ): return var pre_edit = plugin.selection.ply_mesh.begin_edit() - for f_idx in plugin.selection.selected_faces: + + for f_idx: int in (for_faces if !for_faces.is_empty() else plugin.selection.selected_faces): plugin.selection.ply_mesh.set_face_surface(f_idx, s) + plugin.selection.ply_mesh.commit_edit("Paint Face", plugin.get_undo_redo(), pre_edit) @@ -449,6 +594,12 @@ func _edge_cut_loop(): ) + +func _on_snap_checkbox_toggle(state: bool) -> void: + plugin.change_settings_key('snap', state) + + + func _edge_subdivide(): if plugin.ignore_inputs: return diff --git a/addons/ply/gui/toolbar/toolbar.tscn b/addons/ply/gui/toolbar/toolbar.tscn index 7de130c..e980051 100644 --- a/addons/ply/gui/toolbar/toolbar.tscn +++ b/addons/ply/gui/toolbar/toolbar.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=34 format=3 uid="uid://bb7qnjnl0y2lf"] +[gd_scene load_steps=55 format=3 uid="uid://bb7qnjnl0y2lf"] [ext_resource type="Texture2D" uid="uid://da0i0pbup2umf" path="res://addons/ply/icons/dark/select_mesh_dark.png" id="5_5m67v"] [ext_resource type="Texture2D" uid="uid://cb212rtjh5ric" path="res://addons/ply/icons/dark/select_face_dark.png" id="6_yuw87"] @@ -20,13 +20,24 @@ [ext_resource type="Script" path="res://addons/ply/gui/toolbar/github_link.gd" id="18"] [ext_resource type="Texture2D" uid="uid://cfm8umrb1vs7r" path="res://addons/ply/icons/dark/collapse_edge_dark.png" id="18_b8383"] +[sub_resource type="InputEventKey" id="InputEventKey_wjygw"] +device = -1 +shift_pressed = true +keycode = 65 +unicode = 65 + +[sub_resource type="Shortcut" id="Shortcut_ff4jr"] +events = [SubResource("InputEventKey_wjygw")] + [sub_resource type="ButtonGroup" id="ButtonGroup_jgq6o"] -[sub_resource type="InputEventKey" id="InputEventKey_wa7sa"] +[sub_resource type="InputEventKey" id="InputEventKey_l6rws"] +device = -1 keycode = 49 +unicode = 49 -[sub_resource type="Shortcut" id="Shortcut_3n0xq"] -events = [SubResource("InputEventKey_wa7sa")] +[sub_resource type="Shortcut" id="Shortcut_kc1lk"] +events = [SubResource("InputEventKey_l6rws")] [sub_resource type="InputEventKey" id="InputEventKey_477mp"] keycode = 50 @@ -40,14 +51,86 @@ keycode = 51 [sub_resource type="Shortcut" id="8"] events = [SubResource("InputEventKey_g51mm")] -[sub_resource type="InputEventKey" id="InputEventKey_xgrna"] +[sub_resource type="InputEventKey" id="InputEventKey_y7tdk"] +device = -1 keycode = 52 +unicode = 52 + +[sub_resource type="Shortcut" id="Shortcut_vc2bd"] +events = [SubResource("InputEventKey_y7tdk")] + +[sub_resource type="InputEventKey" id="InputEventKey_efma2"] +device = -1 +keycode = 72 +unicode = 104 + +[sub_resource type="InputEventKey" id="InputEventKey_jsfgl"] +device = -1 +keycode = 86 +unicode = 118 -[sub_resource type="Shortcut" id="10"] -events = [SubResource("InputEventKey_xgrna")] +[sub_resource type="Shortcut" id="Shortcut_48tbk"] +events = [SubResource("InputEventKey_efma2"), SubResource("InputEventKey_jsfgl")] [sub_resource type="ButtonGroup" id="ButtonGroup_xlkoy"] +[sub_resource type="InputEventKey" id="InputEventKey_m484a"] +device = -1 +keycode = 84 +unicode = 116 + +[sub_resource type="Shortcut" id="Shortcut_o6fr1"] +events = [SubResource("InputEventKey_m484a")] + +[sub_resource type="InputEventKey" id="InputEventKey_mos2o"] +device = -1 +keycode = 89 +unicode = 121 + +[sub_resource type="Shortcut" id="Shortcut_s2hlu"] +events = [SubResource("InputEventKey_mos2o")] + +[sub_resource type="InputEventKey" id="InputEventKey_i4c01"] +device = -1 +keycode = 85 +unicode = 117 + +[sub_resource type="Shortcut" id="Shortcut_af8g2"] +events = [SubResource("InputEventKey_i4c01")] + +[sub_resource type="InputEventKey" id="InputEventKey_4l3np"] +device = -1 +alt_pressed = true +keycode = 66 + +[sub_resource type="Shortcut" id="Shortcut_ioitr"] +events = [SubResource("InputEventKey_4l3np")] + +[sub_resource type="InputEventKey" id="InputEventKey_e03mk"] +device = -1 +keycode = 73 +unicode = 105 + +[sub_resource type="Shortcut" id="Shortcut_hcfw2"] +events = [SubResource("InputEventKey_e03mk")] + +[sub_resource type="InputEventKey" id="InputEventKey_scx1k"] +device = -1 +keycode = 71 +unicode = 103 + +[sub_resource type="Shortcut" id="Shortcut_evhxi"] +events = [SubResource("InputEventKey_scx1k")] + +[sub_resource type="InputEventKey" id="InputEventKey_5kxv7"] +device = -1 +alt_pressed = true +ctrl_pressed = true +keycode = 69 + +[sub_resource type="Shortcut" id="Shortcut_5ecg7"] +events = [SubResource("InputEventKey_5kxv7")] + [sub_resource type="InputEventKey" id="InputEventKey_qn4mv"] ctrl_pressed = true keycode = 69 @@ -55,6 +138,15 @@ keycode = 69 [sub_resource type="Shortcut" id="12"] events = [SubResource("InputEventKey_qn4mv")] +[sub_resource type="InputEventKey" id="InputEventKey_c3pco"] +device = -1 +shift_pressed = true +ctrl_pressed = true +keycode = 82 + +[sub_resource type="Shortcut" id="Shortcut_wbdn3"] +events = [SubResource("InputEventKey_c3pco")] + [sub_resource type="InputEventKey" id="InputEventKey_ubopt"] ctrl_pressed = true keycode = 82 @@ -120,49 +212,61 @@ color = Color(0.537255, 0.537255, 0.537255, 0.294118) [node name="MarginContainer" type="MarginContainer" parent="Scroll/Content/ToolModeLabel"] layout_mode = 2 -[node name="CenterContainer" type="CenterContainer" parent="Scroll/Content/ToolModeLabel/MarginContainer"] +[node name="Mode" type="Label" parent="Scroll/Content/ToolModeLabel/MarginContainer"] layout_mode = 2 +size_flags_horizontal = 4 +text = "Tool" -[node name="Mode" type="Label" parent="Scroll/Content/ToolModeLabel/MarginContainer/CenterContainer"] +[node name="SelectAll" type="Button" parent="Scroll/Content/ToolModeLabel/MarginContainer"] +custom_minimum_size = Vector2(22, 0) layout_mode = 2 -size_flags_horizontal = 3 -text = "Tool" +size_flags_horizontal = 8 +theme_override_colors/icon_normal_color = Color(0.984314, 0.521569, 0, 1) +shortcut = SubResource("Shortcut_ff4jr") +icon = ExtResource("5_5m67v") +icon_alignment = 1 +expand_icon = true -[node name="Mesh" type="Button" parent="Scroll/Content"] +[node name="Vertex" type="Button" parent="Scroll/Content"] layout_mode = 2 toggle_mode = true -button_pressed = true button_group = SubResource("ButtonGroup_jgq6o") -shortcut = SubResource("Shortcut_3n0xq") -text = "Mesh" -icon = ExtResource("5_5m67v") +shortcut = SubResource("Shortcut_kc1lk") +text = "Vertex" +icon = ExtResource("8_0w4vc") expand_icon = true -[node name="Face" type="Button" parent="Scroll/Content"] +[node name="Edge" type="Button" parent="Scroll/Content"] layout_mode = 2 toggle_mode = true button_group = SubResource("ButtonGroup_jgq6o") shortcut = SubResource("6") -text = "Face" -icon = ExtResource("6_yuw87") +text = "Edge" +icon = ExtResource("7_j2iu8") expand_icon = true -[node name="Edge" type="Button" parent="Scroll/Content"] +[node name="Face" type="Button" parent="Scroll/Content"] layout_mode = 2 toggle_mode = true button_group = SubResource("ButtonGroup_jgq6o") shortcut = SubResource("8") -text = "Edge" -icon = ExtResource("7_j2iu8") +text = "Face" +icon = ExtResource("6_yuw87") expand_icon = true -[node name="Vertex" type="Button" parent="Scroll/Content"] +[node name="Mesh" type="Button" parent="Scroll/Content"] layout_mode = 2 toggle_mode = true button_group = SubResource("ButtonGroup_jgq6o") -shortcut = SubResource("10") -text = "Vertex" -icon = ExtResource("8_0w4vc") +shortcut = SubResource("Shortcut_vc2bd") +text = "Mesh" +icon = ExtResource("5_5m67v") +expand_icon = true + +[node name="SnapCheckbox" type="CheckBox" parent="Scroll/Content"] +layout_mode = 2 +shortcut = SubResource("Shortcut_48tbk") +text = "Snap" expand_icon = true [node name="GizmoModeLabel" type="MarginContainer" parent="Scroll/Content"] @@ -187,18 +291,21 @@ text = "Gizmo Mode" layout_mode = 2 toggle_mode = true button_group = SubResource("ButtonGroup_xlkoy") +shortcut = SubResource("Shortcut_o6fr1") text = "Global" [node name="Local" type="Button" parent="Scroll/Content"] layout_mode = 2 toggle_mode = true button_group = SubResource("ButtonGroup_xlkoy") +shortcut = SubResource("Shortcut_s2hlu") text = "Local" [node name="Normal" type="Button" parent="Scroll/Content"] layout_mode = 2 toggle_mode = true button_group = SubResource("ButtonGroup_xlkoy") +shortcut = SubResource("Shortcut_af8g2") text = "Normal" [node name="Spacer" type="CenterContainer" parent="Scroll/Content"] @@ -206,6 +313,7 @@ layout_mode = 2 size_flags_vertical = 3 [node name="MeshTools" type="VBoxContainer" parent="Scroll/Content"] +visible = false layout_mode = 2 [node name="Tools" type="MarginContainer" parent="Scroll/Content/MeshTools"] @@ -228,6 +336,7 @@ text = "Mesh Tools" [node name="Subdivide" type="Button" parent="Scroll/Content/MeshTools"] layout_mode = 2 +shortcut = SubResource("Shortcut_ioitr") text = "Subdivide" icon = ExtResource("5_5m67v") expand_icon = true @@ -240,6 +349,7 @@ expand_icon = true [node name="InvertNormals" type="Button" parent="Scroll/Content/MeshTools"] layout_mode = 2 +shortcut = SubResource("Shortcut_hcfw2") text = "Invert Normals" icon = ExtResource("10_uborc") expand_icon = true @@ -264,6 +374,7 @@ text = "Mesh Utilities" [node name="Generators" type="Button" parent="Scroll/Content/MeshTools"] layout_mode = 2 +shortcut = SubResource("Shortcut_evhxi") text = "Generate" [node name="Import" type="Button" parent="Scroll/Content/MeshTools"] @@ -272,6 +383,7 @@ text = "Import" [node name="ExportOBJ" type="Button" parent="Scroll/Content/MeshTools"] layout_mode = 2 +shortcut = SubResource("Shortcut_5ecg7") text = "Export to OBJ" [node name="FaceTools" type="VBoxContainer" parent="Scroll/Content"] @@ -361,13 +473,21 @@ color = Color(0.537255, 0.537255, 0.537255, 0.294118) [node name="MarginContainer" type="MarginContainer" parent="Scroll/Content/FaceTools/PaintSurfaces"] layout_mode = 2 -[node name="CenterContainer" type="CenterContainer" parent="Scroll/Content/FaceTools/PaintSurfaces/MarginContainer"] +[node name="HboxContainer" type="HBoxContainer" parent="Scroll/Content/FaceTools/PaintSurfaces/MarginContainer"] layout_mode = 2 -[node name="Tools" type="Label" parent="Scroll/Content/FaceTools/PaintSurfaces/MarginContainer/CenterContainer"] +[node name="Tools" type="Label" parent="Scroll/Content/FaceTools/PaintSurfaces/MarginContainer/HboxContainer"] layout_mode = 2 size_flags_horizontal = 3 text = "Texture" +horizontal_alignment = 1 + +[node name="0" type="Button" parent="Scroll/Content/FaceTools/PaintSurfaces/MarginContainer/HboxContainer"] +custom_minimum_size = Vector2(22, 0) +layout_mode = 2 +size_flags_horizontal = 8 +toggle_mode = true +text = "0" [node name="Surfaces" type="GridContainer" parent="Scroll/Content/FaceTools"] layout_mode = 2 @@ -376,48 +496,147 @@ columns = 3 [node name="1" type="Button" parent="Scroll/Content/FaceTools/Surfaces"] layout_mode = 2 size_flags_horizontal = 3 +toggle_mode = true text = "1" [node name="2" type="Button" parent="Scroll/Content/FaceTools/Surfaces"] layout_mode = 2 size_flags_horizontal = 3 +toggle_mode = true text = "2" [node name="3" type="Button" parent="Scroll/Content/FaceTools/Surfaces"] layout_mode = 2 size_flags_horizontal = 3 +toggle_mode = true text = "3" [node name="4" type="Button" parent="Scroll/Content/FaceTools/Surfaces"] layout_mode = 2 size_flags_horizontal = 3 +toggle_mode = true text = "4" [node name="5" type="Button" parent="Scroll/Content/FaceTools/Surfaces"] layout_mode = 2 size_flags_horizontal = 3 +toggle_mode = true text = "5" [node name="6" type="Button" parent="Scroll/Content/FaceTools/Surfaces"] layout_mode = 2 size_flags_horizontal = 3 +toggle_mode = true text = "6" [node name="7" type="Button" parent="Scroll/Content/FaceTools/Surfaces"] layout_mode = 2 size_flags_horizontal = 3 +toggle_mode = true text = "7" [node name="8" type="Button" parent="Scroll/Content/FaceTools/Surfaces"] layout_mode = 2 size_flags_horizontal = 3 +toggle_mode = true text = "8" [node name="9" type="Button" parent="Scroll/Content/FaceTools/Surfaces"] layout_mode = 2 size_flags_horizontal = 3 +toggle_mode = true text = "9" +[node name="10" type="Button" parent="Scroll/Content/FaceTools/Surfaces"] +visible = false +layout_mode = 2 +size_flags_horizontal = 3 +toggle_mode = true +text = "10" + +[node name="11" type="Button" parent="Scroll/Content/FaceTools/Surfaces"] +visible = false +layout_mode = 2 +size_flags_horizontal = 3 +toggle_mode = true +text = "11" + +[node name="12" type="Button" parent="Scroll/Content/FaceTools/Surfaces"] +visible = false +layout_mode = 2 +size_flags_horizontal = 3 +toggle_mode = true +text = "12" + +[node name="13" type="Button" parent="Scroll/Content/FaceTools/Surfaces"] +visible = false +layout_mode = 2 +size_flags_horizontal = 3 +toggle_mode = true +text = "13" + +[node name="14" type="Button" parent="Scroll/Content/FaceTools/Surfaces"] +visible = false +layout_mode = 2 +size_flags_horizontal = 3 +toggle_mode = true +text = "14" + +[node name="15" type="Button" parent="Scroll/Content/FaceTools/Surfaces"] +visible = false +layout_mode = 2 +size_flags_horizontal = 3 +toggle_mode = true +text = "15" + +[node name="16" type="Button" parent="Scroll/Content/FaceTools/Surfaces"] +visible = false +layout_mode = 2 +size_flags_horizontal = 3 +toggle_mode = true +text = "16" + +[node name="17" type="Button" parent="Scroll/Content/FaceTools/Surfaces"] +visible = false +layout_mode = 2 +size_flags_horizontal = 3 +toggle_mode = true +text = "17" + +[node name="18" type="Button" parent="Scroll/Content/FaceTools/Surfaces"] +visible = false +layout_mode = 2 +size_flags_horizontal = 3 +toggle_mode = true +text = "18" + +[node name="19" type="Button" parent="Scroll/Content/FaceTools/Surfaces"] +visible = false +layout_mode = 2 +size_flags_horizontal = 3 +toggle_mode = true +text = "19" + +[node name="20" type="Button" parent="Scroll/Content/FaceTools/Surfaces"] +visible = false +layout_mode = 2 +size_flags_horizontal = 3 +toggle_mode = true +text = "20" + +[node name="21" type="Button" parent="Scroll/Content/FaceTools/Surfaces"] +visible = false +layout_mode = 2 +size_flags_horizontal = 3 +toggle_mode = true +text = "21" + +[node name="ExpandSurfaces" type="Button" parent="Scroll/Content/FaceTools"] +layout_mode = 2 +size_flags_horizontal = 3 +toggle_mode = true +text = "More" + [node name="VertexColor" type="MarginContainer" parent="Scroll/Content/FaceTools"] layout_mode = 2 @@ -478,6 +697,7 @@ text = "Select Edges" [node name="SelectLoop" type="Button" parent="Scroll/Content/EdgeTools"] layout_mode = 2 +shortcut = SubResource("Shortcut_wbdn3") text = "Loop" icon = ExtResource("15_5b5te") expand_icon = true diff --git a/addons/ply/nodes/ply_faces.gd b/addons/ply/nodes/ply_faces.gd index dcbabd2..cd67cbf 100644 --- a/addons/ply/nodes/ply_faces.gd +++ b/addons/ply/nodes/ply_faces.gd @@ -9,7 +9,7 @@ var m = StandardMaterial3D.new() func _ready() -> void: mesh = ImmediateMesh.new() - m.albedo_color = Color(0, 1, 0, 0.5) + m.albedo_color = Color(0, 1, 0, 0.04) m.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED m.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA m.vertex_color_use_as_albedo = true diff --git a/addons/ply/plugin.gd b/addons/ply/plugin.gd index d37682a..065d6d8 100644 --- a/addons/ply/plugin.gd +++ b/addons/ply/plugin.gd @@ -26,6 +26,33 @@ var transform_gizmo: TransformGizmo var inspector: Inspector var ignore_inputs = false +const DEFAULT_SETTINGS: Dictionary = { #Dictionary[String, Variant] + 'snap': true, +} +var current_settings := DEFAULT_SETTINGS + + + +func save_settings(default := false): + var settings_file := FileAccess.open('res://addons/ply/settings.json', FileAccess.WRITE_READ) + print(settings_file) + settings_file.store_line(JSON.stringify(DEFAULT_SETTINGS if default else current_settings)) + settings_file.close() + if default: + current_settings = DEFAULT_SETTINGS + +func load_settings(): + if not FileAccess.file_exists('res://addons/ply/settings.json'): + save_settings(true) #create file + + var settings_file := FileAccess.open('res://addons/ply/settings.json', FileAccess.READ) + var data: Variant = JSON.parse_string(settings_file.get_as_text()) if settings_file != null else null + if data != null: + current_settings = data + else: + save_settings(true) #overwrite file to default if error + + var toolbar = preload("res://addons/ply/gui/toolbar/toolbar.tscn").instantiate() @@ -48,6 +75,7 @@ func _enter_tree() -> void: selector.startup() add_inspector_plugin(inspector) + load_settings() toolbar.plugin = self toolbar.visible = false add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_SIDE_LEFT, toolbar) @@ -81,6 +109,15 @@ func _clear() -> void: var selection # nullable PlyEditor +func change_settings_key(key: String, value: Variant) -> void: + if !DEFAULT_SETTINGS.has(key): + printerr('PlyEditor: Not found "', key, '" key') + return + current_settings[key] = value + save_settings() + + + func _edit(o: Object) -> void: if selection and not selection.is_queued_for_deletion(): selection.selected = false diff --git a/addons/ply/plugin/selector.gd b/addons/ply/plugin/selector.gd index ffe3016..79c3870 100644 --- a/addons/ply/plugin/selector.gd +++ b/addons/ply/plugin/selector.gd @@ -152,7 +152,7 @@ func handle_input(camera: Camera3D, event: InputEvent) -> bool: drag_position = event.position _plugin.update_overlays() return true - if event.ctrl_pressed: + if _plugin.current_settings.snap: match _plugin.transform_gizmo.edit_mode: 1: # translate snap = _plugin.snap_values.translate diff --git a/addons/ply/utils/selection_mode.gd b/addons/ply/utils/selection_mode.gd index b5a9caf..e7b78eb 100644 --- a/addons/ply/utils/selection_mode.gd +++ b/addons/ply/utils/selection_mode.gd @@ -1 +1 @@ -enum { MESH, FACE, EDGE, VERTEX } +enum { VERTEX, EDGE, FACE, MESH } \ No newline at end of file