1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-03-15 15:55:18 +00:00

Compare commits

..

3 commits

Author SHA1 Message Date
Emmanouil Papadeas
dbfd4d8412 When merging layers, automatically make the bottom layer visible
If the bottom layer is invisible, it becomes visible now. Consistent with behavior seen in Krita and Photopea.
2024-04-09 02:30:50 +03:00
Emmanouil Papadeas
23a480fe7d Update CHANGELOG.md 2024-04-09 01:55:20 +03:00
Emmanouil Papadeas
8f395b2be7 Create a new Effects menu and move all of the cel-specific effects there, away from the Image menu
Also moves Project properties into Image
2024-04-09 01:52:12 +03:00
11 changed files with 86 additions and 50 deletions

View file

@ -20,7 +20,7 @@ Built using Godot 4.2.1
- Alpha lock has been added as a global tool option. When enabled, users can only draw on non-transparent pixels.
- Export to webp and jpeg file formats. Webp is currently only for static images and does not support animations.
- A basic Command Line Interface has been implemented, to help with automating mass project file exporting. [#579](https://github.com/Orama-Interactive/Pixelorama/discussions/579)
- Exporting the project data in a separate JSON file is now possible from the export dialog.
- Exporting the project's data to a separate JSON file is now possible from the export dialog.
- Native file dialogs are now supported and can be enabled from the Preferences!
- Dialog popups can now be native OS windows instead of embedded within Pixelorama's main window. This can be changed from the Preferences.
- Added some missing shortcuts for buttons. [#900](https://github.com/Orama-Interactive/Pixelorama/pull/900)
@ -32,7 +32,7 @@ Built using Godot 4.2.1
- Users can now add custom data in the form of text in their projects, layers, frames, tags and cels.
- Image brushes can now be flipped and rotated with 90 degree steps in the tool options. [#988](https://github.com/Orama-Interactive/Pixelorama/pull/988)
- Added support for inverted tablet pens. [#966](https://github.com/Orama-Interactive/Pixelorama/pull/966)
- Added new dialogs for cel, layer and project properties. Cel and layer which can be accessed by right-clicking cel and the layer buttons in the timeline respectively, while project properties can be found under the Edit menu.
- Added new dialogs for cel, layer and project properties. Cel and layer which can be accessed by right-clicking cel and the layer buttons in the timeline respectively, while project properties can be found under the Image menu.
- A new z-index property has been added to the cel properties, allowing for independent, per-frame layer ordering.
- Pasting tags from other projects is now possible. [#946](https://github.com/Orama-Interactive/Pixelorama/pull/946)
- It is now possible to change the color space of gradients from sRGB, which is the default, to Linear sRGB and Oklab.
@ -49,6 +49,7 @@ Built using Godot 4.2.1
- The color pickers has been vastly improved, thanks to the update to Godot 4. Users can now use the OKHSL color mode, and choose between four different picker shapes: HSV Rectangle (default), HSV Wheel, VHS Circle and OKHSL Circle.
- The opacity slider in the timeline now affects layer opacity and not cel opacity. Cel opacity has been moved to the cel properties dialog.
- The timeline's UI has been changed to better indicate which cels are selected and improves on how child layers of groups are being shown.
- Cel-specific effects have been moved from the Image menu into the new Effects menu.
- Linked cels no longer have a colored outline, they now have a rectangle behind their preview which makes linked cels look like they are chained together.
- "Crop Image" has been renamed to "Crop to Content".
- Imported images automatically become new projects without opening the import dialog, if there is only one project open, and that project is empty.

View file

@ -1878,7 +1878,7 @@ msgstr ""
msgid "Properties"
msgstr ""
msgid "Project properties"
msgid "Project Properties"
msgstr ""
msgid "Frame properties"

View file

@ -164,7 +164,7 @@ class GeneralAPI:
## Gives ability to add/remove items from menus in the top bar.
class MenuAPI:
enum { FILE, EDIT, SELECT, IMAGE, VIEW, WINDOW, HELP }
enum { FILE, EDIT, SELECT, IMAGE, EFFECTS, VIEW, WINDOW, HELP }
# Menu methods
func _get_popup_menu(menu_type: int) -> PopupMenu:
@ -177,6 +177,8 @@ class MenuAPI:
return Global.top_menu_container.select_menu
IMAGE:
return Global.top_menu_container.image_menu
EFFECTS:
return Global.top_menu_container.effects_menu
VIEW:
return Global.top_menu_container.view_menu
WINDOW:
@ -192,7 +194,7 @@ class MenuAPI:
## function inside its script.[br]
## Index of the added item is returned (which can be used to remove menu item later on).
func add_menu_item(menu_type: int, item_name: String, item_metadata, item_id := -1) -> int:
var popup_menu: PopupMenu = _get_popup_menu(menu_type)
var popup_menu := _get_popup_menu(menu_type)
if not popup_menu:
return -1
popup_menu.add_item(item_name, item_id)
@ -206,7 +208,7 @@ class MenuAPI:
## Removes a menu item at index [param item_idx] from the [param menu_type] defined by
## [enum @unnamed_enums].
func remove_menu_item(menu_type: int, item_idx: int) -> void:
var popup_menu: PopupMenu = _get_popup_menu(menu_type)
var popup_menu := _get_popup_menu(menu_type)
if not popup_menu:
return
popup_menu.remove_item(item_idx)

View file

@ -24,9 +24,7 @@ enum MeasurementMode { NONE, MOVE }
## Enumeration of items present in the File Menu.
enum FileMenu { NEW, OPEN, OPEN_LAST_PROJECT, RECENT, SAVE, SAVE_AS, EXPORT, EXPORT_AS, QUIT }
## Enumeration of items present in the Edit Menu.
enum EditMenu {
UNDO, REDO, COPY, CUT, PASTE, PASTE_IN_PLACE, DELETE, NEW_BRUSH, PROJECT_PROPERTIES, PREFERENCES
}
enum EditMenu { UNDO, REDO, COPY, CUT, PASTE, PASTE_IN_PLACE, DELETE, NEW_BRUSH, PREFERENCES }
## Enumeration of items present in the View Menu.
enum ViewMenu {
TILE_MODE,
@ -45,11 +43,15 @@ enum ViewMenu {
enum WindowMenu { WINDOW_OPACITY, PANELS, LAYOUTS, MOVABLE_PANELS, ZEN_MODE, FULLSCREEN_MODE }
## Enumeration of items present in the Image Menu.
enum ImageMenu {
PROJECT_PROPERTIES,
RESIZE_CANVAS,
OFFSET_IMAGE,
SCALE_IMAGE,
CROP_TO_SELECTION,
CROP_TO_CONTENT,
}
## Enumeration of items present in the Effects menu.
enum EffectsMenu {
OFFSET_IMAGE,
FLIP,
ROTATE,
OUTLINE,
@ -721,23 +723,23 @@ func _initialize_keychain() -> void:
"paste_in_place": Keychain.InputAction.new("", "Edit menu", true),
"delete": Keychain.InputAction.new("", "Edit menu", true),
"new_brush": Keychain.InputAction.new("", "Edit menu", true),
&"project_properties": Keychain.InputAction.new("", "Edit menu", true),
"preferences": Keychain.InputAction.new("", "Edit menu", true),
&"project_properties": Keychain.InputAction.new("", "Image menu", true),
"scale_image": Keychain.InputAction.new("", "Image menu", true),
"crop_to_selection": Keychain.InputAction.new("", "Image menu", true),
"crop_to_content": Keychain.InputAction.new("", "Image menu", true),
"resize_canvas": Keychain.InputAction.new("", "Image menu", true),
"offset_image": Keychain.InputAction.new("", "Image menu", true),
"mirror_image": Keychain.InputAction.new("", "Image menu", true),
"rotate_image": Keychain.InputAction.new("", "Image menu", true),
"invert_colors": Keychain.InputAction.new("", "Image menu", true),
"desaturation": Keychain.InputAction.new("", "Image menu", true),
"outline": Keychain.InputAction.new("", "Image menu", true),
"drop_shadow": Keychain.InputAction.new("", "Image menu", true),
"adjust_hsv": Keychain.InputAction.new("", "Image menu", true),
"gradient": Keychain.InputAction.new("", "Image menu", true),
"gradient_map": Keychain.InputAction.new("", "Image menu", true),
"posterize": Keychain.InputAction.new("", "Image menu", true),
"offset_image": Keychain.InputAction.new("", "Effects menu", true),
"mirror_image": Keychain.InputAction.new("", "Effects menu", true),
"rotate_image": Keychain.InputAction.new("", "Effects menu", true),
"invert_colors": Keychain.InputAction.new("", "Effects menu", true),
"desaturation": Keychain.InputAction.new("", "Effects menu", true),
"outline": Keychain.InputAction.new("", "Effects menu", true),
"drop_shadow": Keychain.InputAction.new("", "Effects menu", true),
"adjust_hsv": Keychain.InputAction.new("", "Effects menu", true),
"gradient": Keychain.InputAction.new("", "Effects menu", true),
"gradient_map": Keychain.InputAction.new("", "Effects menu", true),
"posterize": Keychain.InputAction.new("", "Effects menu", true),
"mirror_view": Keychain.InputAction.new("", "View menu", true),
"show_grid": Keychain.InputAction.new("", "View menu", true),
"show_pixel_grid": Keychain.InputAction.new("", "View menu", true),

View file

@ -3,6 +3,7 @@ extends RefCounted
## Base class for layer properties. Different layer types extend from this class.
signal name_changed ## Emits when [member name] is changed.
signal visibility_changed ## Emits when [member visible] is changed.
## All currently supported layer blend modes between two layers. The upper layer
## is the blend layer, and the bottom layer is the base layer.
@ -37,7 +38,10 @@ var name := "": ## Name of the layer.
var project: Project ## The project the layer belongs to.
var index: int ## Index of layer in the timeline.
var parent: BaseLayer ## Parent of the layer.
var visible := true ## Sets visibility of the layer.
var visible := true: ## Sets visibility of the layer.
set(value):
visible = value
visibility_changed.emit()
var locked := false ## Images of a locked layer won't be overritten.
var new_cels_linked := false ## Determines if new cel of the layer should be linked or not.
var blend_mode := BlendModes.NORMAL ## Blend mode of the current layer.

View file

@ -3,7 +3,7 @@
[ext_resource type="Script" path="res://src/UI/Dialogs/ProjectProperties.gd" id="1_0n4uc"]
[node name="ProjectProperties" type="AcceptDialog"]
title = "Project properties"
title = "Project Properties"
size = Vector2i(197, 235)
exclusive = false
popup_window = true

View file

@ -948,7 +948,6 @@ func _on_MergeDownLayer_pressed() -> void:
project.undos += 1
project.undo_redo.create_action("Merge Layer")
for frame in project.frames:
var top_cel := frame.cels[top_layer.index]
top_cels.append(top_cel) # Store for undo purposes
@ -1000,6 +999,7 @@ func _on_MergeDownLayer_pressed() -> void:
project.undo_redo.add_undo_method(Global.undo_or_redo.bind(true))
project.undo_redo.add_do_method(Global.undo_or_redo.bind(false))
project.undo_redo.commit_action()
bottom_layer.visible = true
func _on_OpacitySlider_value_changed(value: float) -> void:

View file

@ -40,11 +40,13 @@ suffix = "x"
[node name="UserDataLabel" type="Label" parent="GridContainer"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 0
text = "User data:"
[node name="UserDataTextEdit" type="TextEdit" parent="GridContainer"]
layout_mode = 2
size_flags_horizontal = 3
scroll_fit_content_height = true
[connection signal="about_to_popup" from="." to="." method="_on_FrameProperties_about_to_show"]

View file

@ -34,6 +34,7 @@ func _ready() -> void:
Global.cel_switched.connect(func(): z_index = 1 if button_pressed else 0)
var layer := Global.current_project.layers[layer_index]
layer.name_changed.connect(func(): label.text = layer.name)
layer.visibility_changed.connect(update_buttons)
if layer is PixelLayer:
linked_button.visible = true
elif layer is GroupLayer:

View file

@ -41,6 +41,7 @@ var about_dialog := Dialog.new("res://src/UI/Dialogs/AboutDialog.tscn")
@onready var edit_menu: PopupMenu = $MenuBar/Edit
@onready var select_menu: PopupMenu = $MenuBar/Select
@onready var image_menu: PopupMenu = $MenuBar/Image
@onready var effects_menu: PopupMenu = $MenuBar/Effects
@onready var view_menu: PopupMenu = $MenuBar/View
@onready var window_menu: PopupMenu = $MenuBar/Window
@onready var help_menu: PopupMenu = $MenuBar/Help
@ -86,6 +87,7 @@ func _ready() -> void:
_setup_view_menu()
_setup_window_menu()
_setup_image_menu()
_setup_effects_menu()
_setup_select_menu()
_setup_help_menu()
@ -172,7 +174,6 @@ func _setup_edit_menu() -> void:
"Paste in Place": "paste_in_place",
"Delete": "delete",
"New Brush": "new_brush",
"Project properties": "project_properties",
"Preferences": "preferences"
}
var i := 0
@ -338,11 +339,24 @@ func populate_layouts_submenu() -> void:
func _setup_image_menu() -> void:
# Order as in Global.ImageMenu enum
var image_menu_items := {
"Project Properties": "project_properties",
"Resize Canvas": "resize_canvas",
"Offset Image": "offset_image",
"Scale Image": "scale_image",
"Crop to Selection": "crop_to_selection",
"Crop to Content": "crop_to_content",
}
var i := 0
for item in image_menu_items:
_set_menu_shortcut(image_menu_items[item], image_menu, i, item)
i += 1
image_menu.set_item_disabled(Global.ImageMenu.CROP_TO_SELECTION, true)
image_menu.id_pressed.connect(image_menu_id_pressed)
func _setup_effects_menu() -> void:
# Order as in Global.EffectMenu enum
var menu_items := {
"Offset Image": "offset_image",
"Mirror Image": "mirror_image",
"Rotate Image": "rotate_image",
"Outline": "outline",
@ -356,11 +370,10 @@ func _setup_image_menu() -> void:
# "Shader": ""
}
var i := 0
for item in image_menu_items:
_set_menu_shortcut(image_menu_items[item], image_menu, i, item)
for item in menu_items:
_set_menu_shortcut(menu_items[item], effects_menu, i, item)
i += 1
image_menu.set_item_disabled(Global.ImageMenu.CROP_TO_SELECTION, true)
image_menu.id_pressed.connect(image_menu_id_pressed)
effects_menu.id_pressed.connect(effects_menu_id_pressed)
func _setup_select_menu() -> void:
@ -530,8 +543,6 @@ func edit_menu_id_pressed(id: int) -> void:
Global.canvas.selection.delete()
Global.EditMenu.NEW_BRUSH:
Global.canvas.selection.new_brush()
Global.EditMenu.PROJECT_PROPERTIES:
project_properties_dialog.popup()
Global.EditMenu.PREFERENCES:
preferences_dialog.popup()
_:
@ -726,40 +737,46 @@ func _toggle_fullscreen() -> void:
func image_menu_id_pressed(id: int) -> void:
match id:
Global.ImageMenu.PROJECT_PROPERTIES:
project_properties_dialog.popup()
Global.ImageMenu.SCALE_IMAGE:
scale_image_dialog.popup()
Global.ImageMenu.OFFSET_IMAGE:
offset_image_dialog.popup()
Global.ImageMenu.CROP_TO_SELECTION:
DrawingAlgos.crop_to_selection()
Global.ImageMenu.CROP_TO_CONTENT:
DrawingAlgos.crop_to_content()
Global.ImageMenu.RESIZE_CANVAS:
resize_canvas_dialog.popup()
Global.ImageMenu.FLIP:
func effects_menu_id_pressed(id: int) -> void:
match id:
Global.EffectsMenu.OFFSET_IMAGE:
offset_image_dialog.popup()
Global.EffectsMenu.FLIP:
mirror_image_dialog.popup()
Global.ImageMenu.ROTATE:
Global.EffectsMenu.ROTATE:
rotate_image_dialog.popup()
Global.ImageMenu.INVERT_COLORS:
Global.EffectsMenu.INVERT_COLORS:
invert_colors_dialog.popup()
Global.ImageMenu.DESATURATION:
Global.EffectsMenu.DESATURATION:
desaturate_dialog.popup()
Global.ImageMenu.OUTLINE:
Global.EffectsMenu.OUTLINE:
outline_dialog.popup()
Global.ImageMenu.DROP_SHADOW:
Global.EffectsMenu.DROP_SHADOW:
drop_shadow_dialog.popup()
Global.ImageMenu.HSV:
Global.EffectsMenu.HSV:
hsv_dialog.popup()
Global.ImageMenu.GRADIENT:
Global.EffectsMenu.GRADIENT:
gradient_dialog.popup()
Global.ImageMenu.GRADIENT_MAP:
Global.EffectsMenu.GRADIENT_MAP:
gradient_map_dialog.popup()
Global.ImageMenu.POSTERIZE:
Global.EffectsMenu.POSTERIZE:
posterize_dialog.popup()
#Global.ImageMenu.SHADER:
#Global.EffectsMenu.SHADER:
#shader_effect_dialog.popup()
_:
_handle_metadata(id, image_menu)
_handle_metadata(id, effects_menu)
func select_menu_id_pressed(id: int) -> void:

View file

@ -24,6 +24,8 @@ flat = true
[node name="Image" type="PopupMenu" parent="MenuBar"]
[node name="Effects" type="PopupMenu" parent="MenuBar"]
[node name="View" type="PopupMenu" parent="MenuBar"]
[node name="Window" type="PopupMenu" parent="MenuBar"]
@ -31,12 +33,15 @@ flat = true
[node name="Help" type="PopupMenu" parent="MenuBar"]
[node name="TopLabels" type="HBoxContainer" parent="."]
layout_mode = 0
layout_mode = 1
anchors_preset = 13
anchor_left = 0.5
anchor_right = 0.5
anchor_bottom = 1.0
offset_left = -65.5
offset_right = 65.5
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/separation = 20
[node name="RotationSlider" type="TextureProgressBar" parent="TopLabels"]
@ -84,7 +89,8 @@ layout_mode = 2
text = "[64×64]"
[node name="HBoxContainer" type="HBoxContainer" parent="."]
layout_mode = 0
layout_mode = 1
anchors_preset = 6
anchor_left = 1.0
anchor_top = 0.5
anchor_right = 1.0
@ -93,7 +99,8 @@ offset_left = -330.0
offset_top = -14.0
offset_right = 0.00012207
offset_bottom = 13.0
grow_horizontal = 2
grow_horizontal = 0
grow_vertical = 2
alignment = 1
[node name="CurrentFrame" type="Label" parent="HBoxContainer"]