1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-01-18 17:19:50 +00:00

Compare commits

..

15 commits

Author SHA1 Message Date
Emmanouil Papadeas a993d7b1be
Merge 83a795e828 into a7a76ff9f0 2024-12-10 15:24:51 +00:00
Emmanouil Papadeas 83a795e828 New translations translations.pot (Spanish) 2024-12-10 17:24:47 +02:00
Emmanouil Papadeas a7a76ff9f0 Enable always on top for more child dialogs of other dialogs
Continuation of c72a1f4b90
2024-12-10 14:36:56 +02:00
Emmanouil Papadeas 11e05ac471 Fix loading project with linked cels
Regression from #1146.
2024-12-09 16:30:53 +02:00
Emmanouil Papadeas 3c3de7823a Fix brush preview turning white for a moment when switching tools
Continuation of b7c34f42
2024-12-09 13:38:58 +02:00
Emmanouil Papadeas aa5c1d3182 Fix wrong current directory of the open and save dialogs
Their current directory was one directory above of the directory it should be
2024-12-09 00:55:22 +02:00
Emmanouil Papadeas 3022963b84 Fix pasting not being snapped to grid when draw tiles mode is enabled 2024-12-09 00:17:43 +02:00
Emmanouil Papadeas 0873a7bf70 Make the tiles panel immediately visible when loading a project at startup that only has tilemap layers 2024-12-09 00:17:24 +02:00
Emmanouil Papadeas 0d2b579afe Don't export the first frame twice when using ping pong loop 2024-12-08 15:40:03 +02:00
Emmanouil Papadeas 9c628c403b Fix stack tile editing mode not increasing the tile's times_used variable 2024-12-07 17:01:56 +02:00
Emmanouil Papadeas d41037d2df Fix tilemap manual editing mode not working with shape & text tools, and fixed issues with the pencil tool
Not the most performance-friendly solution, but it works. If users encounter performance issues in the future, we should rewrite this, as it does the same for loop two times.
2024-12-06 18:06:23 +02:00
Emmanouil Papadeas 65e907e1d2 Do not add an empty tile in the tilesets when loading a pxo file 2024-12-06 15:19:19 +02:00
Emmanouil Papadeas e5c7d46997 Fix crash when saving a loaded pxo file that has tilesets 2024-12-06 15:16:01 +02:00
Emmanouil Papadeas b7c34f4233 Fix pencil/eraser/shading previews turning white for a brief moment when changing image brushes 2024-12-06 04:11:05 +02:00
Emmanouil Papadeas 1ea80a342a Fix some unintentional behaviors with tilemap layer tile editing modes 2024-12-06 04:03:57 +02:00
19 changed files with 114 additions and 62 deletions

View file

@ -10,7 +10,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Language-Team: Spanish\n"
"Language: es_ES\n"
"PO-Revision-Date: 2024-12-05 02:11\n"
"PO-Revision-Date: 2024-12-10 15:24\n"
msgid "OK"
msgstr "OK"
@ -2314,7 +2314,7 @@ msgstr "Agrupar"
#. A tilemap is a type of layer, which is divided by grid cells, the size of which is determined by the tileset it uses. Each grid cell is mapped to a tile in the tileset. Tilemaps can be used to create game levels and layouts.
msgid "Tilemap"
msgstr ""
msgstr "Tilemap"
msgid "Layers"
msgstr "Capas"
@ -2346,7 +2346,7 @@ msgstr "Agregar nueva capa 3D"
#. One of the options of the create new layer button.
#: src/UI/Timeline/AnimationTimeline.tscn
msgid "Add Tilemap Layer"
msgstr ""
msgstr "Añadir capa de Tilemap"
#: src/UI/Timeline/AnimationTimeline.tscn
msgid "Remove current layer"
@ -3056,7 +3056,7 @@ msgstr "Grabador"
#. Tiles are images of a specific shape, usually rectangular, that are laid out in a grid. They are used in tile-based video games. https://en.wikipedia.org/wiki/Tile-based_video_game
msgid "Tiles"
msgstr ""
msgstr "Mosaicos"
msgid "Crop"
msgstr "Recortar"
@ -3467,47 +3467,47 @@ msgstr "¿Deseas descargar la imagen desde %s?"
#: src/Classes/TileSetCustom.gd
#: src/UI/Dialogs/ImportPreviewDialog.gd
msgid "Tileset"
msgstr ""
msgstr "Set de mosaicos"
#. A tileset is a collection of tiles.
#: src/UI/Timeline/NewTileMapLayerDialog.tscn
msgid "Tileset:"
msgstr ""
msgstr "Tileset:"
#. A tileset is a collection of tiles.
#: src/UI/Dialogs/ProjectProperties.tscn
msgid "Tilesets"
msgstr ""
msgstr "Tilesets"
#: src/UI/Timeline/NewTileMapLayerDialog.tscn
msgid "New tileset"
msgstr ""
msgstr "Nuevo tileset"
#: src/UI/Timeline/NewTileMapLayerDialog.tscn
msgid "Tileset name:"
msgstr ""
msgstr "Nombre del tileset:"
#: src/UI/Timeline/NewTileMapLayerDialog.tscn
msgid "Tile size:"
msgstr ""
msgstr "Tamaño de mosaico:"
#: src/UI/TilesPanel.tscn
msgid "Draw tiles"
msgstr ""
msgstr "Dibujar mosaicos"
#: src/UI/TilesPanel.tscn
msgid "Rotate tile left (counterclockwise)"
msgstr ""
msgstr "Rotar mosaico a la izquierda (en sentido antihorario)"
#: src/UI/TilesPanel.tscn
msgid "Rotate tile right (clockwise)"
msgstr ""
msgstr "Rotar mosaico a la derecha (en sentido horario)"
#: src/UI/TilesPanel.tscn
msgid "Flip tile horizontally"
msgstr ""
msgstr "Voltar mosaico horizontalmente"
#: src/UI/TilesPanel.tscn
msgid "Flip tile vertically"
msgstr ""
msgstr "Voltear mosaico verticalmente"

View file

@ -325,6 +325,8 @@ func _calculate_frames(project := Global.current_project) -> Array[Frame]:
var inverted_frames := frames.duplicate()
inverted_frames.reverse()
inverted_frames.remove_at(0)
if inverted_frames.size() > 0:
inverted_frames.remove_at(inverted_frames.size() - 1)
frames.append_array(inverted_frames)
return frames

View file

@ -394,6 +394,7 @@ func update_tilemap(
if _tiles_equal(i, image_portion, tile.image):
if cells[i].index != j:
cells[i].index = j
tileset.tiles[j].times_used += 1
cells[i].remove_transformations()
found_tile = true
break
@ -656,6 +657,21 @@ func update_texture(undo := false) -> void:
var tile_size := current_tile.image.get_size()
image.blit_rect(current_tile.image, Rect2i(Vector2i.ZERO, tile_size), coords)
continue
if not editing_images.has(index):
if not _tiles_equal(i, image_portion, current_tile.image):
var transformed_image := transform_tile(
image_portion, cell_data.flip_h, cell_data.flip_v, cell_data.transpose, true
)
editing_images[index] = [i, transformed_image]
for i in cells.size():
var cell_data := cells[i]
var index := cell_data.index
if index >= tileset.tiles.size():
index = 0
var coords := get_cell_coords_in_image(i)
var rect := Rect2i(coords, tileset.tile_size)
var image_portion := image.get_region(rect)
if editing_images.has(index):
var editing_portion := editing_images[index][0] as int
if i == editing_portion:
@ -670,12 +686,6 @@ func update_texture(undo := false) -> void:
if not image_portion.get_data() == transformed_editing_image.get_data():
var tile_size := image_portion.get_size()
image.blit_rect(transformed_editing_image, Rect2i(Vector2i.ZERO, tile_size), coords)
else:
if not _tiles_equal(i, image_portion, current_tile.image):
var transformed_image := transform_tile(
image_portion, cell_data.flip_h, cell_data.flip_v, cell_data.transpose, true
)
editing_images[index] = [i, transformed_image]
super.update_texture(undo)

View file

@ -157,7 +157,10 @@ func display_animate_dialog() -> void:
func _commit_undo(action: String, undo_data: Dictionary, project: Project) -> void:
project.update_tilemaps(undo_data)
var tile_editing_mode := TileSetPanel.tile_editing_mode
if tile_editing_mode == TileSetPanel.TileEditingMode.MANUAL:
tile_editing_mode = TileSetPanel.TileEditingMode.AUTO
project.update_tilemaps(undo_data, tile_editing_mode)
var redo_data := _get_undo_data(project)
project.undos += 1
project.undo_redo.create_action(action)

View file

@ -16,7 +16,7 @@ var tileset: TileSetCustom
func _init(_project: Project, _tileset: TileSetCustom, _name := "") -> void:
super._init(_project, _name)
tileset = _tileset
if not project.tilesets.has(tileset):
if not project.tilesets.has(tileset) and is_instance_valid(tileset):
project.add_tileset(tileset)

View file

@ -352,7 +352,7 @@ func deserialize(dict: Dictionary, zip_reader: ZIPReader = null, file: FileAcces
if dict.has("tilesets"):
for saved_tileset in dict["tilesets"]:
var tile_size = str_to_var("Vector2i" + saved_tileset.get("tile_size"))
var tileset := TileSetCustom.new(tile_size)
var tileset := TileSetCustom.new(tile_size, "", false)
tileset.deserialize(saved_tileset)
tilesets.append(tileset)
if dict.has("frames") and dict.has("layers"):
@ -367,21 +367,6 @@ func deserialize(dict: Dictionary, zip_reader: ZIPReader = null, file: FileAcces
Global.LayerTypes.TILEMAP:
layers.append(LayerTileMap.new(self, null))
# Parent references to other layers are created when deserializing
# a layer, so loop again after creating them:
for layer_i in dict.layers.size():
layers[layer_i].index = layer_i
var layer_dict: Dictionary = dict.layers[layer_i]
# Ensure that loaded pxo files from v1.0-v1.0.3 have the correct
# blend mode, after the addition of the Erase mode in v1.0.4.
if pxo_version < 4 and layer_dict.has("blend_mode"):
var blend_mode: int = layer_dict.get("blend_mode")
if blend_mode >= BaseLayer.BlendModes.ERASE:
blend_mode += 1
layer_dict["blend_mode"] = blend_mode
layers[layer_i].deserialize(layer_dict)
_deserialize_metadata(layers[layer_i], dict.layers[layer_i])
var frame_i := 0
for frame in dict.frames:
var cels: Array[BaseCel] = []
@ -401,7 +386,9 @@ func deserialize(dict: Dictionary, zip_reader: ZIPReader = null, file: FileAcces
cels.append(Cel3D.new(size, true))
Global.LayerTypes.TILEMAP:
var image := _load_image_from_pxo(frame_i, cel_i, zip_reader, file)
var new_cel := (layer as LayerTileMap).new_cel_from_image(image)
var tileset_index = dict.layers[cel_i].tileset_index
var tileset := tilesets[tileset_index]
var new_cel := CelTileMap.new(tileset, image)
cels.append(new_cel)
cel["pxo_version"] = pxo_version
cels[cel_i].deserialize(cel)
@ -418,6 +405,21 @@ func deserialize(dict: Dictionary, zip_reader: ZIPReader = null, file: FileAcces
_deserialize_metadata(frame_class, frame)
frames.append(frame_class)
frame_i += 1
# Parent references to other layers are created when deserializing
# a layer, so loop again after creating them:
for layer_i in dict.layers.size():
layers[layer_i].index = layer_i
var layer_dict: Dictionary = dict.layers[layer_i]
# Ensure that loaded pxo files from v1.0-v1.0.3 have the correct
# blend mode, after the addition of the Erase mode in v1.0.4.
if pxo_version < 4 and layer_dict.has("blend_mode"):
var blend_mode: int = layer_dict.get("blend_mode")
if blend_mode >= BaseLayer.BlendModes.ERASE:
blend_mode += 1
layer_dict["blend_mode"] = blend_mode
layers[layer_i].deserialize(layer_dict)
_deserialize_metadata(layers[layer_i], dict.layers[layer_i])
if dict.has("tags"):
for tag in dict.tags:
var new_tag := AnimationTag.new(tag.name, Color(tag.color), tag.from, tag.to)
@ -1015,7 +1017,9 @@ func add_tileset(tileset: TileSetCustom) -> void:
## Loops through all cels in [param cel_dictionary], and for [CelTileMap]s,
## it calls [method CelTileMap.update_tilemap].
func update_tilemaps(cel_dictionary: Dictionary) -> void:
func update_tilemaps(
cel_dictionary: Dictionary, tile_editing_mode := TileSetPanel.tile_editing_mode
) -> void:
for cel in cel_dictionary:
if cel is CelTileMap:
(cel as CelTileMap).update_tilemap()
(cel as CelTileMap).update_tilemap(tile_editing_mode)

View file

@ -39,11 +39,12 @@ class Tile:
return times_used <= 0
func _init(_tile_size: Vector2i, _name := "") -> void:
func _init(_tile_size: Vector2i, _name := "", add_empty_tile := true) -> void:
tile_size = _tile_size
name = _name
var empty_image := Image.create_empty(tile_size.x, tile_size.y, false, Image.FORMAT_RGBA8)
tiles.append(Tile.new(empty_image))
if add_empty_tile:
var empty_image := Image.create_empty(tile_size.x, tile_size.y, false, Image.FORMAT_RGBA8)
tiles.append(Tile.new(empty_image))
## Adds a new [param image] as a tile to the tileset.

View file

@ -184,13 +184,6 @@ func _ready() -> void:
Import.import_patterns(Global.path_join_array(Global.data_directories, "Patterns"))
quit_and_save_dialog.add_button("Exit without saving", false, "ExitWithoutSaving")
open_sprite_dialog.current_dir = Global.config_cache.get_value(
"data", "current_dir", OS.get_system_dir(OS.SYSTEM_DIR_DESKTOP)
)
save_sprite_dialog.current_dir = Global.config_cache.get_value(
"data", "current_dir", OS.get_system_dir(OS.SYSTEM_DIR_DESKTOP)
)
_handle_cmdline_arguments()
get_tree().root.files_dropped.connect(_on_files_dropped)
if OS.get_name() == "Android":
@ -215,8 +208,8 @@ func _input(event: InputEvent) -> void:
func _project_switched() -> void:
if Global.current_project.export_directory_path != "":
open_sprite_dialog.current_path = Global.current_project.export_directory_path
save_sprite_dialog.current_path = Global.current_project.export_directory_path
open_sprite_dialog.current_dir = Global.current_project.export_directory_path
save_sprite_dialog.current_dir = Global.current_project.export_directory_path
# Taken from https://github.com/godotengine/godot/blob/3.x/editor/editor_settings.cpp#L1474
@ -427,6 +420,7 @@ func load_last_project() -> void:
# Check if file still exists on disk
var file_path = Global.config_cache.get_value("data", "last_project_path")
load_recent_project_file(file_path)
(func(): Global.cel_switched.emit()).call_deferred()
func load_recent_project_file(path: String) -> void:

View file

@ -1473,6 +1473,7 @@ text = "Pixelorama must be restarted for changes to take effect."
mode = 1
title = "Open File(s)"
size = Vector2i(560, 400)
always_on_top = true
ok_button_text = "Open"
file_mode = 1
access = 2
@ -1484,6 +1485,7 @@ transient = true
[node name="EnableExtensionConfirmation" type="ConfirmationDialog" parent="."]
unique_name_in_owner = true
always_on_top = true
dialog_text = "Are you sure you want to enable this extension? Make sure to only enable extensions from sources that you trust."
dialog_autowrap = true
@ -1491,11 +1493,13 @@ dialog_autowrap = true
unique_name_in_owner = true
position = Vector2i(0, 36)
size = Vector2i(400, 100)
always_on_top = true
ok_button_text = "Delete Permanently"
dialog_text = "Are you sure you want to delete this extension?"
dialog_autowrap = true
[node name="ResetOptionsConfirmation" type="ConfirmationDialog" parent="."]
always_on_top = true
dialog_text = "Are you sure you want to reset the selected options? There will be no way to undo this."
[connection signal="about_to_popup" from="." to="." method="_on_PreferencesDialog_about_to_show"]

View file

@ -212,6 +212,8 @@ func update_brush() -> void:
$DensityValueSlider.visible = _brush.type not in IMAGE_BRUSHES
$ColorInterpolation.visible = _brush.type in IMAGE_BRUSHES
$RotationOptions.visible = _brush.type in IMAGE_BRUSHES
var canvas_indicators := Global.canvas.indicators
canvas_indicators.queue_redraw()
func update_random_image() -> void:
@ -274,6 +276,7 @@ func prepare_undo(action: String) -> void:
func commit_undo() -> void:
var project := Global.current_project
Global.canvas.update_selected_cels_textures(project)
project.update_tilemaps(_undo_data)
var redo_data := _get_undo_data()
var frame := -1

View file

@ -395,3 +395,4 @@ func _exit_tree() -> void:
if is_moving:
draw_end(Global.canvas.current_pixel.floor())
Global.canvas.previews_sprite.texture = null
Global.canvas.indicators.queue_redraw()

View file

@ -131,7 +131,7 @@ func _snap_position(pos: Vector2) -> Vector2:
func _commit_undo(action: String) -> void:
var project := Global.current_project
project.update_tilemaps(_undo_data)
project.update_tilemaps(_undo_data, TileSetPanel.TileEditingMode.AUTO)
var redo_data := _get_undo_data()
var frame := -1
var layer := -1

View file

@ -163,6 +163,7 @@ func text_to_pixels() -> void:
func commit_undo(action: String, undo_data: Dictionary) -> void:
var project := Global.current_project
Global.canvas.update_selected_cels_textures(project)
project.update_tilemaps(undo_data)
var redo_data := _get_undo_data()
var frame := -1

View file

@ -629,7 +629,7 @@ func commit_undo(action: String, undo_data_tmp: Dictionary) -> void:
print("No undo data found!")
return
var project := Global.current_project
project.update_tilemaps(undo_data_tmp)
project.update_tilemaps(undo_data_tmp, TileSetPanel.TileEditingMode.AUTO)
var redo_data := get_undo_data(undo_data_tmp["undo_image"])
project.undos += 1
project.undo_redo.create_action(action)
@ -823,8 +823,23 @@ func paste(in_place := false) -> void:
else:
camera_center.y = 0
big_bounding_rectangle.position = Vector2i(camera_center.floor())
if Tools.is_placing_tiles():
var tileset := (Global.current_project.get_current_cel() as CelTileMap).tileset
var grid_size := tileset.tile_size
big_bounding_rectangle.position = Vector2i(
Tools.snap_to_rectangular_grid_boundary(big_bounding_rectangle.position, grid_size)
)
project.selection_map.move_bitmap_values(Global.current_project, false)
else:
if Tools.is_placing_tiles():
var tileset := (Global.current_project.get_current_cel() as CelTileMap).tileset
var grid_size := tileset.tile_size
project.selection_offset = Tools.snap_to_rectangular_grid_boundary(
project.selection_offset, grid_size
)
big_bounding_rectangle.position = Vector2i(
Tools.snap_to_rectangular_grid_boundary(big_bounding_rectangle.position, grid_size)
)
big_bounding_rectangle = big_bounding_rectangle
temp_rect = big_bounding_rectangle
is_moving_content = true

View file

@ -47,7 +47,10 @@ func _flip_image(cel: Image, affect_selection: bool, project: Project) -> void:
func _commit_undo(action: String, undo_data: Dictionary, project: Project) -> void:
_flip_selection(project)
project.update_tilemaps(undo_data)
var tile_editing_mode := TileSetPanel.tile_editing_mode
if tile_editing_mode == TileSetPanel.TileEditingMode.MANUAL:
tile_editing_mode = TileSetPanel.TileEditingMode.AUTO
project.update_tilemaps(undo_data, tile_editing_mode)
var redo_data := _get_undo_data(project)
project.undos += 1
project.undo_redo.create_action(action)

View file

@ -16,6 +16,7 @@ resource_name = "Layout"
script = ExtResource("3")
root = SubResource("1")
hidden_tabs = {}
windows = {}
save_on_change = false
[node name="ManageLayouts" type="AcceptDialog"]
@ -110,6 +111,7 @@ disabled = true
text = "Delete"
[node name="LayoutSettings" type="ConfirmationDialog" parent="."]
always_on_top = true
[node name="VBoxContainer" type="VBoxContainer" parent="LayoutSettings"]
offset_right = 40.0
@ -131,12 +133,12 @@ text = "Copy from"
[node name="LayoutFrom" type="OptionButton" parent="LayoutSettings/VBoxContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
item_count = 1
selected = 0
item_count = 1
popup/item_0/text = "Current layout"
popup/item_0/id = 0
[node name="DeleteConfirmation" type="ConfirmationDialog" parent="."]
always_on_top = true
dialog_text = "Are you sure you want to delete this layout?"
[connection signal="about_to_popup" from="." to="." method="_on_ManageLayouts_about_to_show"]

View file

@ -12,6 +12,7 @@ size = Vector2i(760, 470)
visible = false
wrap_controls = true
exclusive = true
always_on_top = true
script = ExtResource("1_pwcwi")
[node name="TabContainer" type="TabContainer" parent="."]
@ -24,9 +25,11 @@ offset_left = 7.0
offset_top = 8.0
offset_right = -7.0
offset_bottom = -8.0
current_tab = 0
[node name="Store" type="MarginContainer" parent="TabContainer"]
layout_mode = 2
metadata/_tab_index = 0
[node name="StoreMainContainer" type="HSplitContainer" parent="TabContainer/Store"]
layout_mode = 2
@ -68,6 +71,7 @@ size_flags_horizontal = 3
[node name="Options" type="MarginContainer" parent="TabContainer"]
visible = false
layout_mode = 2
metadata/_tab_index = 1
[node name="ScrollContainer" type="ScrollContainer" parent="TabContainer/Options"]
layout_mode = 2
@ -153,6 +157,7 @@ unique_name_in_owner = true
position = Vector2i(0, 36)
size = Vector2i(511, 326)
unresizable = true
always_on_top = true
popup_window = true
[node name="Content" type="VBoxContainer" parent="Error"]
@ -200,6 +205,7 @@ autowrap_mode = 3
unique_name_in_owner = true
position = Vector2i(0, 36)
size = Vector2i(357, 110)
always_on_top = true
popup_window = true
[node name="Content" type="VBoxContainer" parent="ErrorCustom"]

View file

@ -165,7 +165,10 @@ func _apply_effect(layer: BaseLayer, effect: LayerEffect) -> void:
var shader_image_effect := ShaderImageEffect.new()
shader_image_effect.generate_image(cel_image, effect.shader, effect.params, image_size)
project.update_tilemaps(undo_data)
var tile_editing_mode := TileSetPanel.tile_editing_mode
if tile_editing_mode == TileSetPanel.TileEditingMode.MANUAL:
tile_editing_mode = TileSetPanel.TileEditingMode.AUTO
project.update_tilemaps(undo_data, tile_editing_mode)
for frame in project.frames:
var cel := frame.cels[layer.index]
var cel_image := cel.get_image()

View file

@ -734,7 +734,7 @@ func _color_mode_submenu_id_pressed(id: ColorModes) -> void:
project.color_mode = Image.FORMAT_RGBA8
else:
project.color_mode = Project.INDEXED_MODE
project.update_tilemaps(undo_data)
project.update_tilemaps(undo_data, TileSetPanel.TileEditingMode.AUTO)
project.serialize_cel_undo_data(pixel_cels, redo_data)
project.undo_redo.create_action("Change color mode")
project.undos += 1