Compare commits
140 commits
94db178dc7
...
ab0b1ce9a9
Author | SHA1 | Date | |
---|---|---|---|
ab0b1ce9a9 | |||
d87636e32a | |||
a8392fb14f | |||
8025e3f0ec | |||
01c9ad9a5c | |||
566a53f3f8 | |||
e76ab53e44 | |||
b75977d8e4 | |||
80b58cef8c | |||
a976cd3d9b | |||
2cc2314f00 | |||
288dbbc37e | |||
35d4c26bde | |||
c9f01381f0 | |||
4c7a6b769a | |||
795566e600 | |||
970f8dd1e9 | |||
3e7e8cb560 | |||
39fc26ddd8 | |||
c0bf3a245a | |||
885dc8d1ba | |||
af7237bef8 | |||
d518c6104d | |||
cf18d4a7ca | |||
5d9dc05765 | |||
a234ee9416 | |||
d056c7775f | |||
11d95090d7 | |||
a255f2471b | |||
2115beb457 | |||
88c6395a1b | |||
9480694c8c | |||
89b5b9af33 | |||
9669adee0e | |||
1ae6a09a0c | |||
7d88a89829 | |||
3e94087421 | |||
0ea300f789 | |||
da73e0c2ef | |||
a51294add1 | |||
42292e2edb | |||
905f931ff7 | |||
2c660d228d | |||
09a476d03d | |||
dc6aa68da9 | |||
90834830eb | |||
71699b72bf | |||
d6492973d5 | |||
a1e2fdf7f9 | |||
402ca89124 | |||
a2bddb4cd9 | |||
80f2434d7a | |||
8055f5731e | |||
b7391268b6 | |||
f46b7606e6 | |||
cb4afcd99f | |||
40fbb5950f | |||
6644cbe729 | |||
8186d06714 | |||
0956ba4f56 | |||
5b9eaf77a6 | |||
e524f41f00 | |||
7957ef7f90 | |||
91caefee4a | |||
7de7f3fab8 | |||
2d81bd495a | |||
11ae7c007b | |||
6354856e01 | |||
fede8c3e49 | |||
1710294c9f | |||
8ab4af1047 | |||
8bd31112be | |||
d980eec683 | |||
39c85c3079 | |||
8ceeba76c0 | |||
93eab6929b | |||
1d9b9fda1e | |||
482dbecd13 | |||
cf8dacf0f5 | |||
048058bd35 | |||
605bff7324 | |||
206773c4e7 | |||
b5d5c44c4b | |||
8e55b91a39 | |||
0fad406967 | |||
4b12f764b5 | |||
02d1900dc2 | |||
18e9e2ec56 | |||
6100bdc8df | |||
5ec316a50f | |||
a7a76ff9f0 | |||
11e05ac471 | |||
3c3de7823a | |||
aa5c1d3182 | |||
3022963b84 | |||
0873a7bf70 | |||
0d2b579afe | |||
9c628c403b | |||
d41037d2df | |||
65e907e1d2 | |||
e5c7d46997 | |||
b7c34f4233 | |||
1ea80a342a | |||
f91bb18fb2 | |||
b48bb4a094 | |||
ff5713ae91 | |||
55f83a3367 | |||
c72a1f4b90 | |||
be8b7728e4 | |||
31981a1def | |||
7f4c7a6bf1 | |||
41ea287df4 | |||
a3e372c5d8 | |||
6224d06428 | |||
6459151549 | |||
fe6efb0f1d | |||
8b1367494d | |||
01b55aca07 | |||
5f53a3eb7b | |||
658477ed4b | |||
3fb8484ac5 | |||
0484b1012f | |||
b87a8e2ab8 | |||
e6c4a72158 | |||
1dcb696c35 | |||
d580523c6e | |||
11da07b9ac | |||
7cf87ac142 | |||
bd7d3b19cc | |||
996a234d0d | |||
77f6bcf07b | |||
fede2d8e6f | |||
d0ecf3b03d | |||
3d65e48c92 | |||
aa1731b701 | |||
558140b309 | |||
849b815562 | |||
3615ce087c | |||
2d28136449 | |||
74d95c2424 |
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -15,6 +15,10 @@ https://github.com/Orama-Interactive/Pixelorama/issues?q=is%3Aissue
|
||||||
<!-- Specify commit hash if using a non-official build. -->
|
<!-- Specify commit hash if using a non-official build. -->
|
||||||
|
|
||||||
|
|
||||||
|
**Where did you download Pixelorama from?**
|
||||||
|
<!-- Specify where you downloaded Pixelorama from. GitHub Releases, itch.io, Steam, Flatpak, self-built, somewhere else? -->
|
||||||
|
|
||||||
|
|
||||||
**OS/device including version:**
|
**OS/device including version:**
|
||||||
<!-- Specify GPU model and drivers if graphics-related. -->
|
<!-- Specify GPU model and drivers if graphics-related. -->
|
||||||
|
|
||||||
|
|
32
CHANGELOG.md
|
@ -4,6 +4,36 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). All the dates are in YYYY-MM-DD format.
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). All the dates are in YYYY-MM-DD format.
|
||||||
<br><br>
|
<br><br>
|
||||||
|
|
||||||
|
## [v1.1] - Unreleased
|
||||||
|
This update has been brought to you by the contributions of:
|
||||||
|
Fayez Akhtar ([@Variable-ind](https://github.com/Variable-ind)), Spencer Beckwith ([@spencerjbeckwith](https://github.com/spencerjbeckwith))
|
||||||
|
|
||||||
|
Built using Godot 4.3
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Tilemap layers have arrived! Tilemap layers allow artists to create tiles, and easily preview and dynamically modify them within Pixelorama. [#1146](https://github.com/Orama-Interactive/Pixelorama/pull/1146)
|
||||||
|
- Indexed mode has finally been implemented! [#1136](https://github.com/Orama-Interactive/Pixelorama/pull/1136)
|
||||||
|
- Audio layers have been added, allowing artists to easily synchronize their animations with audio. [#1149](https://github.com/Orama-Interactive/Pixelorama/pull/1149)
|
||||||
|
- Added a new text tool. Destructive only for now, meaning that once the text is confirmed, it cannot be changed later. [#1134](https://github.com/Orama-Interactive/Pixelorama/pull/1134)
|
||||||
|
- A color curves image and layer effect has been added.
|
||||||
|
- It is now possible to load custom Godot shaders as image and layer effects.
|
||||||
|
- Implemented support for multiple grids. [#1122](https://github.com/Orama-Interactive/Pixelorama/pull/1122)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- System font names are now sorted by alphabetical order.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Fixed crash when Pixelorama starts without a palette.
|
||||||
|
- Undo/redo now works again when the cursor is hovering over the timeline.
|
||||||
|
- The first frame is no longer exported twice when using ping-pong loop.
|
||||||
|
- Fixed pencil/eraser/shading previews turning white for a brief moment when changing image brushes, and when switching between tools.
|
||||||
|
- Dialogs that are children of other dialogs now always appear on top, to avoid issues where they could hide behind their parents and causing confusion that made Pixelorama seem unresponsive.
|
||||||
|
- Palette swatches now get deleted when the user removes all palettes.
|
||||||
|
- The CLI's output option now works with filepaths instead of just filenames. [#1145](https://github.com/Orama-Interactive/Pixelorama/pull/1145)
|
||||||
|
- Fixed the Palettize effect and palette exporting to images storing slightly wrong color values. [77f6bcf](https://github.com/Orama-Interactive/Pixelorama/commit/77f6bcf07bd80bc042e478bb883d05900cebe436)
|
||||||
|
- Fixed some issues with the Palettize effect where the output would be different if the palette size changed and empty swatches were added, even if the colors themselves stayed the same. Initially fixed by [bd7d3b1](https://github.com/Orama-Interactive/Pixelorama/commit/bd7d3b19cc98804e9b99754153c4d553d2048ee3), but [1dcb696](https://github.com/Orama-Interactive/Pixelorama/commit/1dcb696c35121f8208bde699f87bb75deff99d13) is the proper fix.
|
||||||
|
- Fixed recorder label not updating when project is changed. [#1139](https://github.com/Orama-Interactive/Pixelorama/pull/1139)
|
||||||
|
|
||||||
## [v1.0.5] - 2024-11-18
|
## [v1.0.5] - 2024-11-18
|
||||||
This update has been brought to you by the contributions of:
|
This update has been brought to you by the contributions of:
|
||||||
Fayez Akhtar ([@Variable-ind](https://github.com/Variable-ind))
|
Fayez Akhtar ([@Variable-ind](https://github.com/Variable-ind))
|
||||||
|
@ -28,7 +58,7 @@ Built using Godot 4.3
|
||||||
- Fixed layer effect slider values being rounded to the nearest integer.
|
- Fixed layer effect slider values being rounded to the nearest integer.
|
||||||
- Fixed memory leak where the project remained referenced by a drawing tool, even when its tab was closed.
|
- Fixed memory leak where the project remained referenced by a drawing tool, even when its tab was closed.
|
||||||
- Fixed memory leak where the first project remained forever references in memory by the Recorder panel.
|
- Fixed memory leak where the first project remained forever references in memory by the Recorder panel.
|
||||||
- Slightly optimize circle brushes by only calling the ellipse algorithms once while drawing
|
- Slightly optimize circle brushes by only calling the ellipse algorithms once while drawing.
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- The Recorder panel has been removed from the Web version. It wasn't functional anyway in a way that was useful, and it's unsure if we can find a way to make it work.
|
- The Recorder panel has been removed from the Web version. It wasn't functional anyway in a way that was useful, and it's unsure if we can find a way to make it work.
|
||||||
|
|
|
@ -3,16 +3,23 @@ Name=Pixelorama
|
||||||
GenericName=2D sprite editor
|
GenericName=2D sprite editor
|
||||||
GenericName[el]=Επεξεργαστής δισδιάστατων εικόνων
|
GenericName[el]=Επεξεργαστής δισδιάστατων εικόνων
|
||||||
GenericName[fr]=Éditeur de sprites 2D
|
GenericName[fr]=Éditeur de sprites 2D
|
||||||
|
GenericName[ru]=2Д редактор спрайтов
|
||||||
GenericName[pt_BR]=Editor de sprites 2D
|
GenericName[pt_BR]=Editor de sprites 2D
|
||||||
|
GenericName[uk]=2Д редактор спрайтів
|
||||||
GenericName[zh_CN]=2D 精灵编辑器
|
GenericName[zh_CN]=2D 精灵编辑器
|
||||||
Comment=Create and edit static or animated 2D sprites
|
Comment=Create and edit static or animated 2D sprites
|
||||||
Comment[el]=Δημιουργήστε και επεξεργαστείτε στατικές ή κινούμενες δισδιάστατες εικόνες
|
Comment[el]=Δημιουργήστε και επεξεργαστείτε στατικές ή κινούμενες δισδιάστατες εικόνες
|
||||||
Comment[fr]=Créez et modifiez des sprites 2D statiques ou animées
|
Comment[fr]=Créez et modifiez des sprites 2D statiques ou animées
|
||||||
|
Comment[ru]=Создавайте и редактируйте статичные и анимированные 2Д спрайты
|
||||||
Comment[pt_BR]=Crie e edite sprites 2D estáticos ou animados
|
Comment[pt_BR]=Crie e edite sprites 2D estáticos ou animados
|
||||||
|
Comment[uk]=Створюйте та редагуйте статичні та анімовані 2Д спрайти
|
||||||
Comment[zh_CN]=创建并编辑 2D 精灵图片或动画
|
Comment[zh_CN]=创建并编辑 2D 精灵图片或动画
|
||||||
Exec=pixelorama
|
Exec=pixelorama
|
||||||
Icon=pixelorama
|
Icon=pixelorama
|
||||||
Terminal=false
|
Terminal=false
|
||||||
Type=Application
|
Type=Application
|
||||||
Categories=Graphics;2DGraphics;RasterGraphics;
|
Categories=Graphics;2DGraphics;RasterGraphics;
|
||||||
|
Keywords=pixel;retro;animation;art;image;2d;sprite;graphics;drawing;editor;
|
||||||
|
Keywords[ru]=pixel;retro;animation;art;image;2d;sprite;graphics;drawing;editor;пиксель;ретро;анимация;арт;изображение;2д;спрайт;графика;рисование;редактор;
|
||||||
|
Keywords[uk]=pixel;retro;animation;art;image;2d;sprite;graphics;drawing;editor;піксель;ретро;анімація;арт;зображення;2д;спрайт;графіка;малювання;редактор;
|
||||||
MimeType=image/pxo;image/png;image/bmp;image/vnd.radiance;image/jpeg;image/svg+xml;image/x-tga;image/webp;
|
MimeType=image/pxo;image/png;image/bmp;image/vnd.radiance;image/jpeg;image/svg+xml;image/x-tga;image/webp;
|
||||||
|
|
|
@ -156,6 +156,18 @@ msgstr ""
|
||||||
msgid "Percentage"
|
msgid "Percentage"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found in the create new image dialog. Allows users to change the color mode of the new project, such as RGBA or indexed mode.
|
||||||
|
msgid "Color mode:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found in the image menu. A submenu that allows users to change the color mode of the project, such as RGBA or indexed mode.
|
||||||
|
msgid "Color Mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found in the image menu, under the "Color Mode" submenu. Refers to the indexed color mode. See this wikipedia page for more information: https://en.wikipedia.org/wiki/Indexed_color
|
||||||
|
msgid "Indexed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. Found in the image menu. Sets the size of the project to be the same as the size of the active selection.
|
#. Found in the image menu. Sets the size of the project to be the same as the size of the active selection.
|
||||||
msgid "Crop to Selection"
|
msgid "Crop to Selection"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -199,6 +211,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1145,6 +1161,27 @@ msgstr ""
|
||||||
msgid "Tint effect factor:"
|
msgid "Tint effect factor:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. An image effect that adjusts the colors of the image by using curves.
|
||||||
|
msgid "Color Curves"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. Refers to a color channel, such as the red, green, blue or alpha channels.
|
||||||
|
msgid "Channel:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Red"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Green"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. Refers to the value (as in HSV) of the colors of an image.
|
||||||
|
msgid "Value"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Presets"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Apply"
|
msgid "Apply"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1494,7 +1531,7 @@ msgstr ""
|
||||||
|
|
||||||
msgid "Text\n\n"
|
msgid "Text\n\n"
|
||||||
"%s for left mouse button\n"
|
"%s for left mouse button\n"
|
||||||
"%s for right mouse button\n\n"
|
"%s for right mouse button"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Rectangle"
|
msgid "Rectangle"
|
||||||
|
@ -1761,6 +1798,10 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
|
msgid "Use dummy audio driver"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#. Found in the Preferences, under Drivers. Specifies the renderer/video driver being used.
|
#. Found in the Preferences, under Drivers. Specifies the renderer/video driver being used.
|
||||||
msgid "Renderer:"
|
msgid "Renderer:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -2191,6 +2232,10 @@ msgstr ""
|
||||||
msgid "Unlink Cels"
|
msgid "Unlink Cels"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. An option found in the right click menu of an audio cel. If selected, the audio of the audio layer will start playing from this frame.
|
||||||
|
msgid "Play audio here"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Properties"
|
msgid "Properties"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2227,6 +2272,13 @@ msgstr ""
|
||||||
msgid "Group"
|
msgid "Group"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. 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 ""
|
||||||
|
|
||||||
|
msgid "Audio"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Layers"
|
msgid "Layers"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2235,33 +2287,52 @@ msgid "Clipping mask"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. Hint tooltip of the create new layer button, found on the left side of the timeline.
|
#. Hint tooltip of the create new layer button, found on the left side of the timeline.
|
||||||
|
#: src/UI/Timeline/AnimationTimeline.tscn
|
||||||
msgid "Create a new layer"
|
msgid "Create a new layer"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. One of the options of the create new layer button.
|
#. One of the options of the create new layer button.
|
||||||
|
#: src/UI/Timeline/AnimationTimeline.tscn
|
||||||
msgid "Add Pixel Layer"
|
msgid "Add Pixel Layer"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. One of the options of the create new layer button.
|
#. One of the options of the create new layer button.
|
||||||
|
#: src/UI/Timeline/AnimationTimeline.tscn
|
||||||
msgid "Add Group Layer"
|
msgid "Add Group Layer"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. One of the options of the create new layer button.
|
#. One of the options of the create new layer button.
|
||||||
|
#: src/UI/Timeline/AnimationTimeline.tscn
|
||||||
msgid "Add 3D Layer"
|
msgid "Add 3D Layer"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. One of the options of the create new layer button.
|
||||||
|
#: src/UI/Timeline/AnimationTimeline.tscn
|
||||||
|
msgid "Add Tilemap Layer"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. One of the options of the create new layer button.
|
||||||
|
#: src/UI/Timeline/AnimationTimeline.tscn
|
||||||
|
msgid "Add Audio Layer"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/UI/Timeline/AnimationTimeline.tscn
|
||||||
msgid "Remove current layer"
|
msgid "Remove current layer"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/UI/Timeline/AnimationTimeline.tscn
|
||||||
msgid "Move up the current layer"
|
msgid "Move up the current layer"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/UI/Timeline/AnimationTimeline.tscn
|
||||||
msgid "Move down the current layer"
|
msgid "Move down the current layer"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/UI/Timeline/AnimationTimeline.tscn
|
||||||
msgid "Clone current layer"
|
msgid "Clone current layer"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/UI/Timeline/AnimationTimeline.tscn
|
||||||
msgid "Merge current layer with the one below"
|
msgid "Merge current layer with the one below"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2375,6 +2446,17 @@ msgstr ""
|
||||||
msgid "Expand/collapse group"
|
msgid "Expand/collapse group"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Refers to the audio file of an audio layer.
|
||||||
|
msgid "Audio file:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Load file"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. An option in the audio layer properties, allows users to play the audio starting from a specific frame.
|
||||||
|
msgid "Play at frame:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Palette"
|
msgid "Palette"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2948,6 +3030,10 @@ msgstr ""
|
||||||
msgid "Recorder"
|
msgid "Recorder"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. 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 ""
|
||||||
|
|
||||||
msgid "Crop"
|
msgid "Crop"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -3349,3 +3435,51 @@ msgstr ""
|
||||||
#. Text from a confirmation dialog that appears when the user is attempting to drag and drop an image directly from the browser into Pixelorama.
|
#. Text from a confirmation dialog that appears when the user is attempting to drag and drop an image directly from the browser into Pixelorama.
|
||||||
msgid "Do you want to download the image from %s?"
|
msgid "Do you want to download the image from %s?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. A tileset is a collection of tiles.
|
||||||
|
#: src/Classes/TileSetCustom.gd
|
||||||
|
#: src/UI/Dialogs/ImportPreviewDialog.gd
|
||||||
|
msgid "Tileset"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. A tileset is a collection of tiles.
|
||||||
|
#: src/UI/Timeline/NewTileMapLayerDialog.tscn
|
||||||
|
msgid "Tileset:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. A tileset is a collection of tiles.
|
||||||
|
#: src/UI/Dialogs/ProjectProperties.tscn
|
||||||
|
msgid "Tilesets"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/UI/Timeline/NewTileMapLayerDialog.tscn
|
||||||
|
msgid "New tileset"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/UI/Timeline/NewTileMapLayerDialog.tscn
|
||||||
|
msgid "Tileset name:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/UI/Timeline/NewTileMapLayerDialog.tscn
|
||||||
|
msgid "Tile size:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/UI/TilesPanel.tscn
|
||||||
|
msgid "Draw tiles"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/UI/TilesPanel.tscn
|
||||||
|
msgid "Rotate tile left (counterclockwise)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/UI/TilesPanel.tscn
|
||||||
|
msgid "Rotate tile right (clockwise)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/UI/TilesPanel.tscn
|
||||||
|
msgid "Flip tile horizontally"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/UI/TilesPanel.tscn
|
||||||
|
msgid "Flip tile vertically"
|
||||||
|
msgstr ""
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Afrikaans\n"
|
"Language-Team: Afrikaans\n"
|
||||||
"Language: af_ZA\n"
|
"Language: af_ZA\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:14\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "Goed"
|
msgstr "Goed"
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Arabic\n"
|
"Language-Team: Arabic\n"
|
||||||
"Language: ar_SA\n"
|
"Language: ar_SA\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:14\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "حسنا"
|
msgstr "حسنا"
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr "الزاوية الأولية:"
|
msgstr "الزاوية الأولية:"
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "مسح"
|
msgstr "مسح"
|
||||||
|
|
||||||
|
@ -1820,7 +1824,7 @@ msgstr "تمكين شفافية النافذة"
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Belarusian\n"
|
"Language-Team: Belarusian\n"
|
||||||
"Language: be_BY\n"
|
"Language: be_BY\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:14\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "OK"
|
msgstr "OK"
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr "Пачатковы вугал:"
|
msgstr "Пачатковы вугал:"
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "Скінуць"
|
msgstr "Скінуць"
|
||||||
|
|
||||||
|
@ -1815,7 +1819,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Bulgarian\n"
|
"Language-Team: Bulgarian\n"
|
||||||
"Language: bg_BG\n"
|
"Language: bg_BG\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:14\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Catalan\n"
|
"Language-Team: Catalan\n"
|
||||||
"Language: ca_ES\n"
|
"Language: ca_ES\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:14\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "D'acord"
|
msgstr "D'acord"
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "Neteja"
|
msgstr "Neteja"
|
||||||
|
|
||||||
|
@ -1853,7 +1857,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Czech\n"
|
"Language-Team: Czech\n"
|
||||||
"Language: cs_CZ\n"
|
"Language: cs_CZ\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:14\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "OK"
|
msgstr "OK"
|
||||||
|
@ -222,6 +222,10 @@ msgstr "Tolerance:"
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr "Počáteční úhel:"
|
msgstr "Počáteční úhel:"
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "Zrušit"
|
msgstr "Zrušit"
|
||||||
|
|
||||||
|
@ -1865,7 +1869,7 @@ msgstr "Povolit průhlednost hlavního okna"
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr "Pokud povoleno, tak se může aplikační okno stát průhledným. Ovlivňuje výkon, takže ponechte vypnuto, pokud funkci nepotřebujete."
|
msgstr "Pokud povoleno, tak se může aplikační okno stát průhledným. Ovlivňuje výkon, takže ponechte vypnuto, pokud funkci nepotřebujete."
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Welsh\n"
|
"Language-Team: Welsh\n"
|
||||||
"Language: cy_GB\n"
|
"Language: cy_GB\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:12\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Danish\n"
|
"Language-Team: Danish\n"
|
||||||
"Language: da_DK\n"
|
"Language: da_DK\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "OK"
|
msgstr "OK"
|
||||||
|
@ -222,6 +222,10 @@ msgstr "Tolerance:"
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr "Indledende vinkel:"
|
msgstr "Indledende vinkel:"
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "Ryd"
|
msgstr "Ryd"
|
||||||
|
|
||||||
|
@ -1853,7 +1857,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: German\n"
|
"Language-Team: German\n"
|
||||||
"Language: de_DE\n"
|
"Language: de_DE\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "OK"
|
msgstr "OK"
|
||||||
|
@ -224,6 +224,10 @@ msgstr "Toleranz:"
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr "Anfangswinkel:"
|
msgstr "Anfangswinkel:"
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "Leeren"
|
msgstr "Leeren"
|
||||||
|
|
||||||
|
@ -1176,24 +1180,24 @@ msgstr "Farbeffekt-Faktor:"
|
||||||
|
|
||||||
#. An image effect that adjusts the colors of the image by using curves.
|
#. An image effect that adjusts the colors of the image by using curves.
|
||||||
msgid "Color Curves"
|
msgid "Color Curves"
|
||||||
msgstr ""
|
msgstr "Farbkurven"
|
||||||
|
|
||||||
#. Refers to a color channel, such as the red, green, blue or alpha channels.
|
#. Refers to a color channel, such as the red, green, blue or alpha channels.
|
||||||
msgid "Channel:"
|
msgid "Channel:"
|
||||||
msgstr ""
|
msgstr "Kanal:"
|
||||||
|
|
||||||
msgid "Red"
|
msgid "Red"
|
||||||
msgstr ""
|
msgstr "Rot"
|
||||||
|
|
||||||
msgid "Green"
|
msgid "Green"
|
||||||
msgstr ""
|
msgstr "Grün"
|
||||||
|
|
||||||
#. Refers to the value (as in HSV) of the colors of an image.
|
#. Refers to the value (as in HSV) of the colors of an image.
|
||||||
msgid "Value"
|
msgid "Value"
|
||||||
msgstr ""
|
msgstr "Wert"
|
||||||
|
|
||||||
msgid "Presets"
|
msgid "Presets"
|
||||||
msgstr ""
|
msgstr "Voreinstellungen"
|
||||||
|
|
||||||
msgid "Apply"
|
msgid "Apply"
|
||||||
msgstr "Übernehmen"
|
msgstr "Übernehmen"
|
||||||
|
@ -1868,7 +1872,7 @@ msgstr "Fenster-Transparenz aktivieren"
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr "Wenn aktiviert, kann das Anwendungsfenster transparent werden. Dies wirkt sich jedoch negative auf die Leistung aus, schalten Sie die Option deshalb aus, solange Sie sie nicht benötigen."
|
msgstr "Wenn aktiviert, kann das Anwendungsfenster transparent werden. Dies wirkt sich jedoch negative auf die Leistung aus, schalten Sie die Option deshalb aus, solange Sie sie nicht benötigen."
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr "Dummy-Audio-Treiber verwenden"
|
msgstr "Dummy-Audio-Treiber verwenden"
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Greek\n"
|
"Language-Team: Greek\n"
|
||||||
"Language: el_GR\n"
|
"Language: el_GR\n"
|
||||||
"PO-Revision-Date: 2024-12-16 14:21\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "Εντάξει"
|
msgstr "Εντάξει"
|
||||||
|
@ -224,6 +224,10 @@ msgstr "Ανοχή:"
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr "Αρχική γωνία:"
|
msgstr "Αρχική γωνία:"
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "Εκκαθάριση"
|
msgstr "Εκκαθάριση"
|
||||||
|
|
||||||
|
@ -1869,7 +1873,7 @@ msgstr "Ενεργοποίηση διαφάνειας παραθύρου"
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr "Αν ενεργοποιηθεί, το παράθυρο της εφαρμογής μπορεί να γίνει διαφανές. Αυτό επηρεάζει τις επιδόσεις, οπότε κρατήστε το απενεργοποιημένο αν δεν το χρειάζεστε."
|
msgstr "Αν ενεργοποιηθεί, το παράθυρο της εφαρμογής μπορεί να γίνει διαφανές. Αυτό επηρεάζει τις επιδόσεις, οπότε κρατήστε το απενεργοποιημένο αν δεν το χρειάζεστε."
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr "Χρήση εικονικού οδηγού ήχου"
|
msgstr "Χρήση εικονικού οδηγού ήχου"
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Pirate English\n"
|
"Language-Team: Pirate English\n"
|
||||||
"Language: en_PT\n"
|
"Language: en_PT\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:12\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Esperanto\n"
|
"Language-Team: Esperanto\n"
|
||||||
"Language: eo_UY\n"
|
"Language: eo_UY\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:12\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "Bone"
|
msgstr "Bone"
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1806,7 +1810,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Spanish\n"
|
"Language-Team: Spanish\n"
|
||||||
"Language: es_ES\n"
|
"Language: es_ES\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:14\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "OK"
|
msgstr "OK"
|
||||||
|
@ -222,6 +222,10 @@ msgstr "Tolerancia:"
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr "Ángulo inicial:"
|
msgstr "Ángulo inicial:"
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "Limpiar"
|
msgstr "Limpiar"
|
||||||
|
|
||||||
|
@ -1865,7 +1869,7 @@ msgstr "Habilitar transparencia de ventana"
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr "Si está activado, la ventana de la aplicación puede ser transparente. Esto afecta al rendimiento, así que mantenlo apagado si no lo necesitas."
|
msgstr "Si está activado, la ventana de la aplicación puede ser transparente. Esto afecta al rendimiento, así que mantenlo apagado si no lo necesitas."
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr "Usar controlador de audio de pruebas"
|
msgstr "Usar controlador de audio de pruebas"
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Estonian\n"
|
"Language-Team: Estonian\n"
|
||||||
"Language: et_EE\n"
|
"Language: et_EE\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Persian\n"
|
"Language-Team: Persian\n"
|
||||||
"Language: fa_IR\n"
|
"Language: fa_IR\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:12\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "باشه"
|
msgstr "باشه"
|
||||||
|
@ -224,6 +224,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1806,7 +1810,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Finnish\n"
|
"Language-Team: Finnish\n"
|
||||||
"Language: fi_FI\n"
|
"Language: fi_FI\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "OK"
|
msgstr "OK"
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Filipino\n"
|
"Language-Team: Filipino\n"
|
||||||
"Language: fil_PH\n"
|
"Language: fil_PH\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:12\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: French\n"
|
"Language-Team: French\n"
|
||||||
"Language: fr_FR\n"
|
"Language: fr_FR\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:14\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "OK"
|
msgstr "OK"
|
||||||
|
@ -223,6 +223,10 @@ msgstr "Tolérance :"
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr "Angle initial :"
|
msgstr "Angle initial :"
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "Effacer"
|
msgstr "Effacer"
|
||||||
|
|
||||||
|
@ -1857,7 +1861,7 @@ msgstr "Activer la transparence de fenêtre"
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr "Si cette option est activée, la fenêtre d'application peut devenir transparente. Cela affecte les performances, donc désactivez-la si vous n'en avez pas besoin."
|
msgstr "Si cette option est activée, la fenêtre d'application peut devenir transparente. Cela affecte les performances, donc désactivez-la si vous n'en avez pas besoin."
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Irish\n"
|
"Language-Team: Irish\n"
|
||||||
"Language: ga_IE\n"
|
"Language: ga_IE\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Ancient Greek\n"
|
"Language-Team: Ancient Greek\n"
|
||||||
"Language: grc\n"
|
"Language: grc\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:12\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "Ἐντάξει"
|
msgstr "Ἐντάξει"
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Hebrew\n"
|
"Language-Team: Hebrew\n"
|
||||||
"Language: he_IL\n"
|
"Language: he_IL\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "אישור"
|
msgstr "אישור"
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1809,7 +1813,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Hindi\n"
|
"Language-Team: Hindi\n"
|
||||||
"Language: hi_IN\n"
|
"Language: hi_IN\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:12\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "ठीक है"
|
msgstr "ठीक है"
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "साफ करें"
|
msgstr "साफ करें"
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Croatian\n"
|
"Language-Team: Croatian\n"
|
||||||
"Language: hr_HR\n"
|
"Language: hr_HR\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Hungarian\n"
|
"Language-Team: Hungarian\n"
|
||||||
"Language: hu_HU\n"
|
"Language: hu_HU\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "Ok"
|
msgstr "Ok"
|
||||||
|
@ -222,6 +222,10 @@ msgstr "Tűréshatár:"
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "Törlés"
|
msgstr "Törlés"
|
||||||
|
|
||||||
|
@ -1815,7 +1819,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Indonesian\n"
|
"Language-Team: Indonesian\n"
|
||||||
"Language: id_ID\n"
|
"Language: id_ID\n"
|
||||||
"PO-Revision-Date: 2024-12-15 21:25\n"
|
"PO-Revision-Date: 2024-12-17 00:52\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "Oke"
|
msgstr "Oke"
|
||||||
|
@ -224,6 +224,10 @@ msgstr "Toleransi:"
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr "Sudut inisial:"
|
msgstr "Sudut inisial:"
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr "Balut Guratan"
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "Kosongkan"
|
msgstr "Kosongkan"
|
||||||
|
|
||||||
|
@ -1869,7 +1873,7 @@ msgstr "Aktifkan transparansi jendela"
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr "Jika diaktifkan, jendela aplikasi akan tampil transparan. Ini juga menguras kinerja, nonaktifkan saja jika tidak perlu."
|
msgstr "Jika diaktifkan, jendela aplikasi akan tampil transparan. Ini juga menguras kinerja, nonaktifkan saja jika tidak perlu."
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr "Gunakan kandar audio bonekaan"
|
msgstr "Gunakan kandar audio bonekaan"
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Icelandic\n"
|
"Language-Team: Icelandic\n"
|
||||||
"Language: is_IS\n"
|
"Language: is_IS\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Italian\n"
|
"Language-Team: Italian\n"
|
||||||
"Language: it_IT\n"
|
"Language: it_IT\n"
|
||||||
"PO-Revision-Date: 2024-12-16 01:01\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "OK"
|
msgstr "OK"
|
||||||
|
@ -224,6 +224,10 @@ msgstr "Tolleranza:"
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr "Angolo iniziale:"
|
msgstr "Angolo iniziale:"
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "Cancella"
|
msgstr "Cancella"
|
||||||
|
|
||||||
|
@ -1869,7 +1873,7 @@ msgstr "Abilita trasparenza finestra"
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr "Se abilitata, la finestra dell'applicazione può diventare trasparente. Ciò influisce sulle prestazioni, quindi tenerla spenta se non ne hai bisogno."
|
msgstr "Se abilitata, la finestra dell'applicazione può diventare trasparente. Ciò influisce sulle prestazioni, quindi tenerla spenta se non ne hai bisogno."
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr "Usa driver audio fittizio"
|
msgstr "Usa driver audio fittizio"
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Japanese\n"
|
"Language-Team: Japanese\n"
|
||||||
"Language: ja_JP\n"
|
"Language: ja_JP\n"
|
||||||
"PO-Revision-Date: 2024-12-16 05:33\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "OK"
|
msgstr "OK"
|
||||||
|
@ -224,6 +224,10 @@ msgstr "許容範囲:"
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr "初期角度:"
|
msgstr "初期角度:"
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "削除"
|
msgstr "削除"
|
||||||
|
|
||||||
|
@ -1869,7 +1873,7 @@ msgstr "ウィンドウの透明度を有効化"
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr "有効にすると、アプリケーションウィンドウは透明になります。これはパフォーマンスに影響しますので、必要がない場合はオフにしておいてください。"
|
msgstr "有効にすると、アプリケーションウィンドウは透明になります。これはパフォーマンスに影響しますので、必要がない場合はオフにしておいてください。"
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Kazakh\n"
|
"Language-Team: Kazakh\n"
|
||||||
"Language: kk_KZ\n"
|
"Language: kk_KZ\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Korean\n"
|
"Language-Team: Korean\n"
|
||||||
"Language: ko_KR\n"
|
"Language: ko_KR\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "예"
|
msgstr "예"
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "초기화"
|
msgstr "초기화"
|
||||||
|
|
||||||
|
@ -1851,7 +1855,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Latin\n"
|
"Language-Team: Latin\n"
|
||||||
"Language: la_LA\n"
|
"Language: la_LA\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:12\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Lithuanian\n"
|
"Language-Team: Lithuanian\n"
|
||||||
"Language: lt_LT\n"
|
"Language: lt_LT\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Latvian\n"
|
"Language-Team: Latvian\n"
|
||||||
"Language: lv_LV\n"
|
"Language: lv_LV\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "Labi"
|
msgstr "Labi"
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1813,7 +1817,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Maori\n"
|
"Language-Team: Maori\n"
|
||||||
"Language: mi_NZ\n"
|
"Language: mi_NZ\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:12\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Macedonian\n"
|
"Language-Team: Macedonian\n"
|
||||||
"Language: mk_MK\n"
|
"Language: mk_MK\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Malayalam\n"
|
"Language-Team: Malayalam\n"
|
||||||
"Language: ml_IN\n"
|
"Language: ml_IN\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:12\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "ഓക്കേ"
|
msgstr "ഓക്കേ"
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Marathi\n"
|
"Language-Team: Marathi\n"
|
||||||
"Language: mr_IN\n"
|
"Language: mr_IN\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Malay\n"
|
"Language-Team: Malay\n"
|
||||||
"Language: ms_MY\n"
|
"Language: ms_MY\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:12\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Norwegian Bokmal\n"
|
"Language-Team: Norwegian Bokmal\n"
|
||||||
"Language: nb_NO\n"
|
"Language: nb_NO\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:12\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "OK"
|
msgstr "OK"
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "Nullstill"
|
msgstr "Nullstill"
|
||||||
|
|
||||||
|
@ -1850,7 +1854,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Dutch\n"
|
"Language-Team: Dutch\n"
|
||||||
"Language: nl_NL\n"
|
"Language: nl_NL\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "Oké"
|
msgstr "Oké"
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "Wissen"
|
msgstr "Wissen"
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Polish\n"
|
"Language-Team: Polish\n"
|
||||||
"Language: pl_PL\n"
|
"Language: pl_PL\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:14\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "OK"
|
msgstr "OK"
|
||||||
|
@ -224,6 +224,10 @@ msgstr "Tolerancja:"
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr "Kąt początkowy:"
|
msgstr "Kąt początkowy:"
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "Usuń zaznaczenie"
|
msgstr "Usuń zaznaczenie"
|
||||||
|
|
||||||
|
@ -1866,7 +1870,7 @@ msgstr "Włącz przezroczystość okna"
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr "Jeśli ta opcja jest włączona, okno aplikacji może stać się przezroczyste. Ma to na wpływ wydajność, więc wyłącz tę opcję, jeśli jej nie potrzebujesz."
|
msgstr "Jeśli ta opcja jest włączona, okno aplikacji może stać się przezroczyste. Ma to na wpływ wydajność, więc wyłącz tę opcję, jeśli jej nie potrzebujesz."
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Portuguese, Brazilian\n"
|
"Language-Team: Portuguese, Brazilian\n"
|
||||||
"Language: pt_BR\n"
|
"Language: pt_BR\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "OK"
|
msgstr "OK"
|
||||||
|
@ -224,6 +224,10 @@ msgstr "Tolerância:"
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr "Ângulo inicial:"
|
msgstr "Ângulo inicial:"
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "Limpar"
|
msgstr "Limpar"
|
||||||
|
|
||||||
|
@ -1867,7 +1871,7 @@ msgstr "Ativar transparência de janela"
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr "Se essa opção estiver ativada, a janela do aplicativo pode ficar transparente. Isso afeta o desempenho, então deixe-a desativada se não precisar dela."
|
msgstr "Se essa opção estiver ativada, a janela do aplicativo pode ficar transparente. Isso afeta o desempenho, então deixe-a desativada se não precisar dela."
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Portuguese\n"
|
"Language-Team: Portuguese\n"
|
||||||
"Language: pt_PT\n"
|
"Language: pt_PT\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "OK"
|
msgstr "OK"
|
||||||
|
@ -222,6 +222,10 @@ msgstr "Tolerância:"
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr "Ângulo inicial:"
|
msgstr "Ângulo inicial:"
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "Limpar"
|
msgstr "Limpar"
|
||||||
|
|
||||||
|
@ -1846,7 +1850,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Romanian\n"
|
"Language-Team: Romanian\n"
|
||||||
"Language: ro_RO\n"
|
"Language: ro_RO\n"
|
||||||
"PO-Revision-Date: 2024-12-15 21:25\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "OK"
|
msgstr "OK"
|
||||||
|
@ -222,6 +222,10 @@ msgstr "Toleranță:"
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr "Unghi inițial:"
|
msgstr "Unghi inițial:"
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "Ștergere"
|
msgstr "Ștergere"
|
||||||
|
|
||||||
|
@ -1867,7 +1871,7 @@ msgstr "Activează transparența ferestrei"
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr "Dacă opțiunea este activată, fereastra aplicației poate deveni transparentă. Aceasta afectează performanța, așa că este recomandată dezactivarea opțiunii dacă nu este necesară."
|
msgstr "Dacă opțiunea este activată, fereastra aplicației poate deveni transparentă. Aceasta afectează performanța, așa că este recomandată dezactivarea opțiunii dacă nu este necesară."
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Russian\n"
|
"Language-Team: Russian\n"
|
||||||
"Language: ru_RU\n"
|
"Language: ru_RU\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "OK"
|
msgstr "OK"
|
||||||
|
@ -223,6 +223,10 @@ msgstr "Допустимое отклонение:"
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr "Начальный угол:"
|
msgstr "Начальный угол:"
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "Очистить"
|
msgstr "Очистить"
|
||||||
|
|
||||||
|
@ -1863,7 +1867,7 @@ msgstr "Включить прозрачность окна"
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr "Если этот параметр включен, окно приложения становится прозрачным. При проблемах с производительностью, отключите эту настройку."
|
msgstr "Если этот параметр включен, окно приложения становится прозрачным. При проблемах с производительностью, отключите эту настройку."
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Sinhala\n"
|
"Language-Team: Sinhala\n"
|
||||||
"Language: si_LK\n"
|
"Language: si_LK\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:12\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "හරි"
|
msgstr "හරි"
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Slovak\n"
|
"Language-Team: Slovak\n"
|
||||||
"Language: sk_SK\n"
|
"Language: sk_SK\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Slovenian\n"
|
"Language-Team: Slovenian\n"
|
||||||
"Language: sl_SI\n"
|
"Language: sl_SI\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Albanian\n"
|
"Language-Team: Albanian\n"
|
||||||
"Language: sq_AL\n"
|
"Language: sq_AL\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "Ne rregull"
|
msgstr "Ne rregull"
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Serbian (Cyrillic)\n"
|
"Language-Team: Serbian (Cyrillic)\n"
|
||||||
"Language: sr_SP\n"
|
"Language: sr_SP\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "ОК"
|
msgstr "ОК"
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "Брисати"
|
msgstr "Брисати"
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Swedish\n"
|
"Language-Team: Swedish\n"
|
||||||
"Language: sv_SE\n"
|
"Language: sv_SE\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "Okej"
|
msgstr "Okej"
|
||||||
|
@ -222,6 +222,10 @@ msgstr "Tolerans:"
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr "Ursprunglig vinkel:"
|
msgstr "Ursprunglig vinkel:"
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "Rensa"
|
msgstr "Rensa"
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Swahili\n"
|
"Language-Team: Swahili\n"
|
||||||
"Language: sw_KE\n"
|
"Language: sw_KE\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:12\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Tamil\n"
|
"Language-Team: Tamil\n"
|
||||||
"Language: ta_IN\n"
|
"Language: ta_IN\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Thai\n"
|
"Language-Team: Thai\n"
|
||||||
"Language: th_TH\n"
|
"Language: th_TH\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Klingon\n"
|
"Language-Team: Klingon\n"
|
||||||
"Language: tlh_AA\n"
|
"Language: tlh_AA\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:12\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Turkish\n"
|
"Language-Team: Turkish\n"
|
||||||
"Language: tr_TR\n"
|
"Language: tr_TR\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "Tamam"
|
msgstr "Tamam"
|
||||||
|
@ -224,6 +224,10 @@ msgstr "Tolerans:"
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr "Başlangıç açısı:"
|
msgstr "Başlangıç açısı:"
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "Temizle"
|
msgstr "Temizle"
|
||||||
|
|
||||||
|
@ -1869,7 +1873,7 @@ msgstr "Pencere saydamlığını etkinleştir"
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr "Etkinleştirilirse uygulama penceresi saydam olur. Başarımı etkilediği için ihtiyacınız yoksa kapatınız."
|
msgstr "Etkinleştirilirse uygulama penceresi saydam olur. Başarımı etkilediği için ihtiyacınız yoksa kapatınız."
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Ukrainian\n"
|
"Language-Team: Ukrainian\n"
|
||||||
"Language: uk_UA\n"
|
"Language: uk_UA\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "Гаразд"
|
msgstr "Гаразд"
|
||||||
|
@ -224,6 +224,10 @@ msgstr "Допустиме відхилення:"
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr "Початковий кут:"
|
msgstr "Початковий кут:"
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "Очистити"
|
msgstr "Очистити"
|
||||||
|
|
||||||
|
@ -1857,7 +1861,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Vietnamese\n"
|
"Language-Team: Vietnamese\n"
|
||||||
"Language: vi_VN\n"
|
"Language: vi_VN\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "OK"
|
msgstr "OK"
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1804,7 +1808,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Chinese Simplified\n"
|
"Language-Team: Chinese Simplified\n"
|
||||||
"Language: zh_CN\n"
|
"Language: zh_CN\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:14\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "确定"
|
msgstr "确定"
|
||||||
|
@ -224,6 +224,10 @@ msgstr "容差:"
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr "初始角度:"
|
msgstr "初始角度:"
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr "取消选中"
|
msgstr "取消选中"
|
||||||
|
|
||||||
|
@ -1868,7 +1872,7 @@ msgstr "启用窗口透明度"
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr "如果启用,应用程序窗口可以变得透明。 这会影响性能,因此如果不需要,请将其关闭。"
|
msgstr "如果启用,应用程序窗口可以变得透明。 这会影响性能,因此如果不需要,请将其关闭。"
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Language-Team: Chinese Traditional\n"
|
"Language-Team: Chinese Traditional\n"
|
||||||
"Language: zh_TW\n"
|
"Language: zh_TW\n"
|
||||||
"PO-Revision-Date: 2024-12-15 20:15\n"
|
"PO-Revision-Date: 2024-12-16 23:11\n"
|
||||||
|
|
||||||
msgid "OK"
|
msgid "OK"
|
||||||
msgstr "確定"
|
msgstr "確定"
|
||||||
|
@ -222,6 +222,10 @@ msgstr ""
|
||||||
msgid "Initial angle:"
|
msgid "Initial angle:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. Found under the Select menu, It's a checkbox that, if enabled, wraps around brush strokes if some part of them goes out of selection bounds.
|
||||||
|
msgid "Wrap Strokes"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1814,7 +1818,7 @@ msgstr ""
|
||||||
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
msgid "If enabled, the application window can become transparent. This affects performance, so keep it off if you don't need it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. An option found in the preferences, under the Performance section.
|
#. An option found in the preferences, under the Performance section. A dummy driver is basically a driver that doesn't do anything. When this option is enabled, audio does not play, but it can help save some performance.
|
||||||
msgid "Use dummy audio driver"
|
msgid "Use dummy audio driver"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
1
assets/graphics/misc/mirror_x.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="none" stroke="#e0e0e0" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6 2 8l2 2M2 8h11m-1-2 2 2-2 2"/></svg>
|
After Width: | Height: | Size: 206 B |
37
assets/graphics/misc/mirror_x.svg.import
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bpsfilx47bw3r"
|
||||||
|
path="res://.godot/imported/mirror_x.svg-16a0646fb607af92a2ccf231dd0f1d98.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/graphics/misc/mirror_x.svg"
|
||||||
|
dest_files=["res://.godot/imported/mirror_x.svg-16a0646fb607af92a2ccf231dd0f1d98.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
|
svg/scale=1.0
|
||||||
|
editor/scale_with_editor_scale=false
|
||||||
|
editor/convert_colors_with_editor_theme=false
|
1
assets/graphics/misc/mirror_y.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><path fill="none" stroke="#e0e0e0" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 4 8 2 6 4m2-2v11m2-1-2 2-2-2"/></svg>
|
After Width: | Height: | Size: 206 B |
37
assets/graphics/misc/mirror_y.svg.import
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bk6iaxiyl74ih"
|
||||||
|
path="res://.godot/imported/mirror_y.svg-47cb90f0f94e4ed7c37f151a9ddbaab0.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/graphics/misc/mirror_y.svg"
|
||||||
|
dest_files=["res://.godot/imported/mirror_y.svg-47cb90f0f94e4ed7c37f151a9ddbaab0.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
|
svg/scale=1.0
|
||||||
|
editor/scale_with_editor_scale=false
|
||||||
|
editor/convert_colors_with_editor_theme=false
|
BIN
assets/graphics/misc/musical_note.png
Normal file
After Width: | Height: | Size: 192 B |
34
assets/graphics/misc/musical_note.png.import
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dfjd72smxp6ma"
|
||||||
|
path="res://.godot/imported/musical_note.png-f1be7cc6341733e6ffe2fa5b650b80c2.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/graphics/misc/musical_note.png"
|
||||||
|
dest_files=["res://.godot/imported/musical_note.png-f1be7cc6341733e6ffe2fa5b650b80c2.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
BIN
assets/graphics/misc/x_minus_y_mirror_off.png
Normal file
After Width: | Height: | Size: 218 B |
34
assets/graphics/misc/x_minus_y_mirror_off.png.import
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://1kj5gcswa3t2"
|
||||||
|
path="res://.godot/imported/x_minus_y_mirror_off.png-da237e3b5b7ad1dfef1c935385f53dc5.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/graphics/misc/x_minus_y_mirror_off.png"
|
||||||
|
dest_files=["res://.godot/imported/x_minus_y_mirror_off.png-da237e3b5b7ad1dfef1c935385f53dc5.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
BIN
assets/graphics/misc/x_minus_y_mirror_on.png
Normal file
After Width: | Height: | Size: 187 B |
34
assets/graphics/misc/x_minus_y_mirror_on.png.import
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dn14bkxwdqsfk"
|
||||||
|
path="res://.godot/imported/x_minus_y_mirror_on.png-0e9186904d8241facc4a0c1190f32c53.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/graphics/misc/x_minus_y_mirror_on.png"
|
||||||
|
dest_files=["res://.godot/imported/x_minus_y_mirror_on.png-0e9186904d8241facc4a0c1190f32c53.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
BIN
assets/graphics/misc/xy_mirror_off.png
Normal file
After Width: | Height: | Size: 183 B |
34
assets/graphics/misc/xy_mirror_off.png.import
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dlxhm0ronna25"
|
||||||
|
path="res://.godot/imported/xy_mirror_off.png-8d2fd9ebdf350f0cd384fdf39fed4ec1.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/graphics/misc/xy_mirror_off.png"
|
||||||
|
dest_files=["res://.godot/imported/xy_mirror_off.png-8d2fd9ebdf350f0cd384fdf39fed4ec1.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
BIN
assets/graphics/misc/xy_mirror_on.png
Normal file
After Width: | Height: | Size: 185 B |
34
assets/graphics/misc/xy_mirror_on.png.import
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://cu2uqp5oupt80"
|
||||||
|
path="res://.godot/imported/xy_mirror_on.png-95d443df3b6d17add41283bdd720ea7e.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/graphics/misc/xy_mirror_on.png"
|
||||||
|
dest_files=["res://.godot/imported/xy_mirror_on.png-95d443df3b6d17add41283bdd720ea7e.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
Before Width: | Height: | Size: 218 B After Width: | Height: | Size: 374 B |
Before Width: | Height: | Size: 162 B After Width: | Height: | Size: 136 B |
BIN
assets/graphics/tileset/place_tiles_disabled.png
Normal file
After Width: | Height: | Size: 204 B |
34
assets/graphics/tileset/place_tiles_disabled.png.import
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bqr3n3tm8b6w2"
|
||||||
|
path="res://.godot/imported/place_tiles_disabled.png-f43e25b0863e3eedf3c6fc7ef902127f.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/graphics/tileset/place_tiles_disabled.png"
|
||||||
|
dest_files=["res://.godot/imported/place_tiles_disabled.png-f43e25b0863e3eedf3c6fc7ef902127f.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
BIN
assets/graphics/tileset/place_tiles_enabled.png
Normal file
After Width: | Height: | Size: 185 B |
34
assets/graphics/tileset/place_tiles_enabled.png.import
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dga8nirhhgyc4"
|
||||||
|
path="res://.godot/imported/place_tiles_enabled.png-845e4dd5c3bbd38cc7bf5ee82ed05667.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/graphics/tileset/place_tiles_enabled.png"
|
||||||
|
dest_files=["res://.godot/imported/place_tiles_enabled.png-845e4dd5c3bbd38cc7bf5ee82ed05667.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
|
@ -1,30 +1,44 @@
|
||||||
[gd_resource type="Resource" script_class="DockableLayout" load_steps=27 format=3 uid="uid://4xtpiowddm7p"]
|
[gd_resource type="Resource" script_class="DockableLayout" load_steps=29 format=3 uid="uid://4xtpiowddm7p"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://addons/dockable_container/layout_panel.gd" id="1"]
|
[ext_resource type="Script" path="res://addons/dockable_container/layout_panel.gd" id="1_jxh43"]
|
||||||
[ext_resource type="Script" path="res://addons/dockable_container/layout_split.gd" id="2"]
|
[ext_resource type="Script" path="res://addons/dockable_container/layout_split.gd" id="2_lw52w"]
|
||||||
[ext_resource type="Script" path="res://addons/dockable_container/layout.gd" id="3"]
|
[ext_resource type="Script" path="res://addons/dockable_container/layout.gd" id="3_4h5wj"]
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_atmme"]
|
[sub_resource type="Resource" id="Resource_atmme"]
|
||||||
resource_name = "Tabs"
|
resource_name = "Tabs"
|
||||||
script = ExtResource("1")
|
script = ExtResource("1_jxh43")
|
||||||
names = PackedStringArray("Tools")
|
names = PackedStringArray("Tools")
|
||||||
current_tab = 0
|
current_tab = 0
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_4b0py"]
|
||||||
|
resource_name = "Tabs"
|
||||||
|
script = ExtResource("1_jxh43")
|
||||||
|
names = PackedStringArray("Tiles")
|
||||||
|
current_tab = 0
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_epagr"]
|
||||||
|
resource_name = "Split"
|
||||||
|
script = ExtResource("2_lw52w")
|
||||||
|
direction = 1
|
||||||
|
percent = 0.5
|
||||||
|
first = SubResource("Resource_atmme")
|
||||||
|
second = SubResource("Resource_4b0py")
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_ouvfk"]
|
[sub_resource type="Resource" id="Resource_ouvfk"]
|
||||||
resource_name = "Tabs"
|
resource_name = "Tabs"
|
||||||
script = ExtResource("1")
|
script = ExtResource("1_jxh43")
|
||||||
names = PackedStringArray("Main Canvas")
|
names = PackedStringArray("Main Canvas")
|
||||||
current_tab = 0
|
current_tab = 0
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_an0ef"]
|
[sub_resource type="Resource" id="Resource_an0ef"]
|
||||||
resource_name = "Tabs"
|
resource_name = "Tabs"
|
||||||
script = ExtResource("1")
|
script = ExtResource("1_jxh43")
|
||||||
names = PackedStringArray("Perspective Editor")
|
names = PackedStringArray("Perspective Editor")
|
||||||
current_tab = 0
|
current_tab = 0
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_xgnjk"]
|
[sub_resource type="Resource" id="Resource_xgnjk"]
|
||||||
resource_name = "Split"
|
resource_name = "Split"
|
||||||
script = ExtResource("2")
|
script = ExtResource("2_lw52w")
|
||||||
direction = 0
|
direction = 0
|
||||||
percent = 0.5
|
percent = 0.5
|
||||||
first = SubResource("Resource_ouvfk")
|
first = SubResource("Resource_ouvfk")
|
||||||
|
@ -32,13 +46,13 @@ second = SubResource("Resource_an0ef")
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_o7cqb"]
|
[sub_resource type="Resource" id="Resource_o7cqb"]
|
||||||
resource_name = "Tabs"
|
resource_name = "Tabs"
|
||||||
script = ExtResource("1")
|
script = ExtResource("1_jxh43")
|
||||||
names = PackedStringArray("Second Canvas")
|
names = PackedStringArray("Second Canvas")
|
||||||
current_tab = 0
|
current_tab = 0
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_ataha"]
|
[sub_resource type="Resource" id="Resource_ataha"]
|
||||||
resource_name = "Split"
|
resource_name = "Split"
|
||||||
script = ExtResource("2")
|
script = ExtResource("2_lw52w")
|
||||||
direction = 0
|
direction = 0
|
||||||
percent = 0.980952
|
percent = 0.980952
|
||||||
first = SubResource("Resource_xgnjk")
|
first = SubResource("Resource_xgnjk")
|
||||||
|
@ -46,13 +60,13 @@ second = SubResource("Resource_o7cqb")
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_8y4au"]
|
[sub_resource type="Resource" id="Resource_8y4au"]
|
||||||
resource_name = "Tabs"
|
resource_name = "Tabs"
|
||||||
script = ExtResource("1")
|
script = ExtResource("1_jxh43")
|
||||||
names = PackedStringArray("Animation Timeline")
|
names = PackedStringArray("Animation Timeline")
|
||||||
current_tab = 0
|
current_tab = 0
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_q2jwk"]
|
[sub_resource type="Resource" id="Resource_q2jwk"]
|
||||||
resource_name = "Split"
|
resource_name = "Split"
|
||||||
script = ExtResource("2")
|
script = ExtResource("2_lw52w")
|
||||||
direction = 1
|
direction = 1
|
||||||
percent = 0.75578
|
percent = 0.75578
|
||||||
first = SubResource("Resource_ataha")
|
first = SubResource("Resource_ataha")
|
||||||
|
@ -60,19 +74,19 @@ second = SubResource("Resource_8y4au")
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_5r0ap"]
|
[sub_resource type="Resource" id="Resource_5r0ap"]
|
||||||
resource_name = "Tabs"
|
resource_name = "Tabs"
|
||||||
script = ExtResource("1")
|
script = ExtResource("1_jxh43")
|
||||||
names = PackedStringArray("Canvas Preview")
|
names = PackedStringArray("Canvas Preview")
|
||||||
current_tab = 0
|
current_tab = 0
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_6pqxe"]
|
[sub_resource type="Resource" id="Resource_6pqxe"]
|
||||||
resource_name = "Tabs"
|
resource_name = "Tabs"
|
||||||
script = ExtResource("1")
|
script = ExtResource("1_jxh43")
|
||||||
names = PackedStringArray("Recorder")
|
names = PackedStringArray("Recorder")
|
||||||
current_tab = 0
|
current_tab = 0
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_ln20x"]
|
[sub_resource type="Resource" id="Resource_ln20x"]
|
||||||
resource_name = "Split"
|
resource_name = "Split"
|
||||||
script = ExtResource("2")
|
script = ExtResource("2_lw52w")
|
||||||
direction = 1
|
direction = 1
|
||||||
percent = 0.911765
|
percent = 0.911765
|
||||||
first = SubResource("Resource_5r0ap")
|
first = SubResource("Resource_5r0ap")
|
||||||
|
@ -80,39 +94,39 @@ second = SubResource("Resource_6pqxe")
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_dksrd"]
|
[sub_resource type="Resource" id="Resource_dksrd"]
|
||||||
resource_name = "Tabs"
|
resource_name = "Tabs"
|
||||||
script = ExtResource("1")
|
script = ExtResource("1_jxh43")
|
||||||
names = PackedStringArray("Global Tool Options")
|
names = PackedStringArray("Global Tool Options")
|
||||||
current_tab = 0
|
current_tab = 0
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_kmey0"]
|
[sub_resource type="Resource" id="Resource_kmey0"]
|
||||||
resource_name = "Tabs"
|
resource_name = "Tabs"
|
||||||
script = ExtResource("1")
|
script = ExtResource("1_jxh43")
|
||||||
names = PackedStringArray("Color Picker", "Reference Images")
|
names = PackedStringArray("Color Picker", "Reference Images")
|
||||||
current_tab = 0
|
current_tab = 0
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_1tm61"]
|
[sub_resource type="Resource" id="Resource_1tm61"]
|
||||||
resource_name = "Split"
|
resource_name = "Split"
|
||||||
script = ExtResource("2")
|
script = ExtResource("2_lw52w")
|
||||||
direction = 1
|
direction = 1
|
||||||
percent = 0.134307
|
percent = 0.0499712
|
||||||
first = SubResource("Resource_dksrd")
|
first = SubResource("Resource_dksrd")
|
||||||
second = SubResource("Resource_kmey0")
|
second = SubResource("Resource_kmey0")
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_btl4b"]
|
[sub_resource type="Resource" id="Resource_btl4b"]
|
||||||
resource_name = "Tabs"
|
resource_name = "Tabs"
|
||||||
script = ExtResource("1")
|
script = ExtResource("1_jxh43")
|
||||||
names = PackedStringArray("Left Tool Options")
|
names = PackedStringArray("Left Tool Options")
|
||||||
current_tab = 0
|
current_tab = 0
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_eu0mc"]
|
[sub_resource type="Resource" id="Resource_eu0mc"]
|
||||||
resource_name = "Tabs"
|
resource_name = "Tabs"
|
||||||
script = ExtResource("1")
|
script = ExtResource("1_jxh43")
|
||||||
names = PackedStringArray("Right Tool Options")
|
names = PackedStringArray("Right Tool Options")
|
||||||
current_tab = 0
|
current_tab = 0
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_8ff4m"]
|
[sub_resource type="Resource" id="Resource_8ff4m"]
|
||||||
resource_name = "Split"
|
resource_name = "Split"
|
||||||
script = ExtResource("2")
|
script = ExtResource("2_lw52w")
|
||||||
direction = 0
|
direction = 0
|
||||||
percent = 0.5
|
percent = 0.5
|
||||||
first = SubResource("Resource_btl4b")
|
first = SubResource("Resource_btl4b")
|
||||||
|
@ -120,21 +134,21 @@ second = SubResource("Resource_eu0mc")
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_e72nu"]
|
[sub_resource type="Resource" id="Resource_e72nu"]
|
||||||
resource_name = "Split"
|
resource_name = "Split"
|
||||||
script = ExtResource("2")
|
script = ExtResource("2_lw52w")
|
||||||
direction = 1
|
direction = 1
|
||||||
percent = 0.660142
|
percent = 0.643859
|
||||||
first = SubResource("Resource_1tm61")
|
first = SubResource("Resource_1tm61")
|
||||||
second = SubResource("Resource_8ff4m")
|
second = SubResource("Resource_8ff4m")
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_sg54a"]
|
[sub_resource type="Resource" id="Resource_sg54a"]
|
||||||
resource_name = "Tabs"
|
resource_name = "Tabs"
|
||||||
script = ExtResource("1")
|
script = ExtResource("1_jxh43")
|
||||||
names = PackedStringArray("Palettes")
|
names = PackedStringArray("Palettes")
|
||||||
current_tab = 0
|
current_tab = 0
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_gdwmg"]
|
[sub_resource type="Resource" id="Resource_gdwmg"]
|
||||||
resource_name = "Split"
|
resource_name = "Split"
|
||||||
script = ExtResource("2")
|
script = ExtResource("2_lw52w")
|
||||||
direction = 1
|
direction = 1
|
||||||
percent = 0.82948
|
percent = 0.82948
|
||||||
first = SubResource("Resource_e72nu")
|
first = SubResource("Resource_e72nu")
|
||||||
|
@ -142,7 +156,7 @@ second = SubResource("Resource_sg54a")
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_acda3"]
|
[sub_resource type="Resource" id="Resource_acda3"]
|
||||||
resource_name = "Split"
|
resource_name = "Split"
|
||||||
script = ExtResource("2")
|
script = ExtResource("2_lw52w")
|
||||||
direction = 1
|
direction = 1
|
||||||
percent = 0.0549133
|
percent = 0.0549133
|
||||||
first = SubResource("Resource_ln20x")
|
first = SubResource("Resource_ln20x")
|
||||||
|
@ -150,30 +164,31 @@ second = SubResource("Resource_gdwmg")
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_2qk0j"]
|
[sub_resource type="Resource" id="Resource_2qk0j"]
|
||||||
resource_name = "Split"
|
resource_name = "Split"
|
||||||
script = ExtResource("2")
|
script = ExtResource("2_lw52w")
|
||||||
direction = 0
|
direction = 0
|
||||||
percent = 0.731967
|
percent = 0.704098
|
||||||
first = SubResource("Resource_q2jwk")
|
first = SubResource("Resource_q2jwk")
|
||||||
second = SubResource("Resource_acda3")
|
second = SubResource("Resource_acda3")
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_msuil"]
|
[sub_resource type="Resource" id="Resource_msuil"]
|
||||||
resource_name = "Split"
|
resource_name = "Split"
|
||||||
script = ExtResource("2")
|
script = ExtResource("2_lw52w")
|
||||||
direction = 0
|
direction = 0
|
||||||
percent = 0.0
|
percent = 0.0
|
||||||
first = SubResource("Resource_atmme")
|
first = SubResource("Resource_epagr")
|
||||||
second = SubResource("Resource_2qk0j")
|
second = SubResource("Resource_2qk0j")
|
||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
resource_name = "Default"
|
resource_name = "Default"
|
||||||
script = ExtResource("3")
|
script = ExtResource("3_4h5wj")
|
||||||
root = SubResource("Resource_msuil")
|
root = SubResource("Resource_msuil")
|
||||||
hidden_tabs = {
|
hidden_tabs = {
|
||||||
"Canvas Preview": true,
|
"Canvas Preview": true,
|
||||||
"Color Picker Sliders": true,
|
"Color Picker Sliders": true,
|
||||||
"Perspective Editor": true,
|
"Perspective Editor": true,
|
||||||
"Recorder": true,
|
"Recorder": true,
|
||||||
"Second Canvas": true
|
"Second Canvas": true,
|
||||||
|
"Tiles": true
|
||||||
}
|
}
|
||||||
windows = {}
|
windows = {}
|
||||||
save_on_change = false
|
save_on_change = false
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
[gd_resource type="Resource" script_class="DockableLayout" load_steps=23 format=3 uid="uid://brcnmadkdaqok"]
|
[gd_resource type="Resource" script_class="DockableLayout" load_steps=25 format=3 uid="uid://brcnmadkdaqok"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://addons/dockable_container/layout_panel.gd" id="1_nokpu"]
|
[ext_resource type="Script" path="res://addons/dockable_container/layout_panel.gd" id="1_t44r1"]
|
||||||
[ext_resource type="Script" path="res://addons/dockable_container/layout_split.gd" id="2_q5vl6"]
|
[ext_resource type="Script" path="res://addons/dockable_container/layout_split.gd" id="2_rngtv"]
|
||||||
[ext_resource type="Script" path="res://addons/dockable_container/layout.gd" id="3_ox7l5"]
|
[ext_resource type="Script" path="res://addons/dockable_container/layout.gd" id="3_v86xb"]
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_kn4x4"]
|
[sub_resource type="Resource" id="Resource_kn4x4"]
|
||||||
resource_name = "Tabs"
|
resource_name = "Tabs"
|
||||||
script = ExtResource("1_nokpu")
|
script = ExtResource("1_t44r1")
|
||||||
names = PackedStringArray("Main Canvas")
|
names = PackedStringArray("Main Canvas")
|
||||||
current_tab = 0
|
current_tab = 0
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_btw27"]
|
[sub_resource type="Resource" id="Resource_btw27"]
|
||||||
resource_name = "Tabs"
|
resource_name = "Tabs"
|
||||||
script = ExtResource("1_nokpu")
|
script = ExtResource("1_t44r1")
|
||||||
names = PackedStringArray("Second Canvas")
|
names = PackedStringArray("Second Canvas")
|
||||||
current_tab = 0
|
current_tab = 0
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_bp28t"]
|
[sub_resource type="Resource" id="Resource_bp28t"]
|
||||||
resource_name = "Split"
|
resource_name = "Split"
|
||||||
script = ExtResource("2_q5vl6")
|
script = ExtResource("2_rngtv")
|
||||||
direction = 0
|
direction = 0
|
||||||
percent = 0.829091
|
percent = 0.829091
|
||||||
first = SubResource("Resource_kn4x4")
|
first = SubResource("Resource_kn4x4")
|
||||||
|
@ -26,13 +26,13 @@ second = SubResource("Resource_btw27")
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_10g0s"]
|
[sub_resource type="Resource" id="Resource_10g0s"]
|
||||||
resource_name = "Tabs"
|
resource_name = "Tabs"
|
||||||
script = ExtResource("1_nokpu")
|
script = ExtResource("1_t44r1")
|
||||||
names = PackedStringArray("Perspective Editor")
|
names = PackedStringArray("Perspective Editor")
|
||||||
current_tab = 0
|
current_tab = 0
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_otntk"]
|
[sub_resource type="Resource" id="Resource_otntk"]
|
||||||
resource_name = "Split"
|
resource_name = "Split"
|
||||||
script = ExtResource("2_q5vl6")
|
script = ExtResource("2_rngtv")
|
||||||
direction = 0
|
direction = 0
|
||||||
percent = 0.8625
|
percent = 0.8625
|
||||||
first = SubResource("Resource_bp28t")
|
first = SubResource("Resource_bp28t")
|
||||||
|
@ -40,25 +40,25 @@ second = SubResource("Resource_10g0s")
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_12axs"]
|
[sub_resource type="Resource" id="Resource_12axs"]
|
||||||
resource_name = "Tabs"
|
resource_name = "Tabs"
|
||||||
script = ExtResource("1_nokpu")
|
script = ExtResource("1_t44r1")
|
||||||
names = PackedStringArray("Tools")
|
names = PackedStringArray("Tools")
|
||||||
current_tab = 0
|
current_tab = 0
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_1omiw"]
|
[sub_resource type="Resource" id="Resource_1omiw"]
|
||||||
resource_name = "Tabs"
|
resource_name = "Tabs"
|
||||||
script = ExtResource("1_nokpu")
|
script = ExtResource("1_t44r1")
|
||||||
names = PackedStringArray("Left Tool Options", "Right Tool Options")
|
names = PackedStringArray("Left Tool Options", "Right Tool Options")
|
||||||
current_tab = 0
|
current_tab = 0
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_p32ds"]
|
[sub_resource type="Resource" id="Resource_p32ds"]
|
||||||
resource_name = "Tabs"
|
resource_name = "Tabs"
|
||||||
script = ExtResource("1_nokpu")
|
script = ExtResource("1_t44r1")
|
||||||
names = PackedStringArray("Color Picker")
|
names = PackedStringArray("Color Picker")
|
||||||
current_tab = 0
|
current_tab = 0
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_n6xyc"]
|
[sub_resource type="Resource" id="Resource_n6xyc"]
|
||||||
resource_name = "Split"
|
resource_name = "Split"
|
||||||
script = ExtResource("2_q5vl6")
|
script = ExtResource("2_rngtv")
|
||||||
direction = 0
|
direction = 0
|
||||||
percent = 0.5
|
percent = 0.5
|
||||||
first = SubResource("Resource_1omiw")
|
first = SubResource("Resource_1omiw")
|
||||||
|
@ -66,19 +66,19 @@ second = SubResource("Resource_p32ds")
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_1dcep"]
|
[sub_resource type="Resource" id="Resource_1dcep"]
|
||||||
resource_name = "Tabs"
|
resource_name = "Tabs"
|
||||||
script = ExtResource("1_nokpu")
|
script = ExtResource("1_t44r1")
|
||||||
names = PackedStringArray("Canvas Preview", "Reference Images", "Recorder")
|
names = PackedStringArray("Canvas Preview", "Reference Images", "Recorder")
|
||||||
current_tab = 0
|
current_tab = 0
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_hc3ve"]
|
[sub_resource type="Resource" id="Resource_hc3ve"]
|
||||||
resource_name = "Tabs"
|
resource_name = "Tabs"
|
||||||
script = ExtResource("1_nokpu")
|
script = ExtResource("1_t44r1")
|
||||||
names = PackedStringArray("Global Tool Options")
|
names = PackedStringArray("Global Tool Options")
|
||||||
current_tab = 0
|
current_tab = 0
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_nppps"]
|
[sub_resource type="Resource" id="Resource_nppps"]
|
||||||
resource_name = "Split"
|
resource_name = "Split"
|
||||||
script = ExtResource("2_q5vl6")
|
script = ExtResource("2_rngtv")
|
||||||
direction = 1
|
direction = 1
|
||||||
percent = 0.729839
|
percent = 0.729839
|
||||||
first = SubResource("Resource_1dcep")
|
first = SubResource("Resource_1dcep")
|
||||||
|
@ -86,13 +86,13 @@ second = SubResource("Resource_hc3ve")
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_d54jb"]
|
[sub_resource type="Resource" id="Resource_d54jb"]
|
||||||
resource_name = "Tabs"
|
resource_name = "Tabs"
|
||||||
script = ExtResource("1_nokpu")
|
script = ExtResource("1_t44r1")
|
||||||
names = PackedStringArray("Palettes")
|
names = PackedStringArray("Palettes")
|
||||||
current_tab = 0
|
current_tab = 0
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_f6rik"]
|
[sub_resource type="Resource" id="Resource_f6rik"]
|
||||||
resource_name = "Split"
|
resource_name = "Split"
|
||||||
script = ExtResource("2_q5vl6")
|
script = ExtResource("2_rngtv")
|
||||||
direction = 0
|
direction = 0
|
||||||
percent = 0.5
|
percent = 0.5
|
||||||
first = SubResource("Resource_nppps")
|
first = SubResource("Resource_nppps")
|
||||||
|
@ -100,7 +100,7 @@ second = SubResource("Resource_d54jb")
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_26vov"]
|
[sub_resource type="Resource" id="Resource_26vov"]
|
||||||
resource_name = "Split"
|
resource_name = "Split"
|
||||||
script = ExtResource("2_q5vl6")
|
script = ExtResource("2_rngtv")
|
||||||
direction = 0
|
direction = 0
|
||||||
percent = 0.501251
|
percent = 0.501251
|
||||||
first = SubResource("Resource_n6xyc")
|
first = SubResource("Resource_n6xyc")
|
||||||
|
@ -108,21 +108,35 @@ second = SubResource("Resource_f6rik")
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_m3axb"]
|
[sub_resource type="Resource" id="Resource_m3axb"]
|
||||||
resource_name = "Tabs"
|
resource_name = "Tabs"
|
||||||
script = ExtResource("1_nokpu")
|
script = ExtResource("1_t44r1")
|
||||||
names = PackedStringArray("Animation Timeline")
|
names = PackedStringArray("Animation Timeline")
|
||||||
current_tab = 0
|
current_tab = 0
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_8dhxy"]
|
||||||
|
resource_name = "Tabs"
|
||||||
|
script = ExtResource("1_t44r1")
|
||||||
|
names = PackedStringArray("Tiles")
|
||||||
|
current_tab = 0
|
||||||
|
|
||||||
|
[sub_resource type="Resource" id="Resource_j3q3h"]
|
||||||
|
resource_name = "Split"
|
||||||
|
script = ExtResource("2_rngtv")
|
||||||
|
direction = 0
|
||||||
|
percent = 0.5
|
||||||
|
first = SubResource("Resource_m3axb")
|
||||||
|
second = SubResource("Resource_8dhxy")
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_af0bk"]
|
[sub_resource type="Resource" id="Resource_af0bk"]
|
||||||
resource_name = "Split"
|
resource_name = "Split"
|
||||||
script = ExtResource("2_q5vl6")
|
script = ExtResource("2_rngtv")
|
||||||
direction = 1
|
direction = 1
|
||||||
percent = 0.5
|
percent = 0.5
|
||||||
first = SubResource("Resource_26vov")
|
first = SubResource("Resource_26vov")
|
||||||
second = SubResource("Resource_m3axb")
|
second = SubResource("Resource_j3q3h")
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_1xpva"]
|
[sub_resource type="Resource" id="Resource_1xpva"]
|
||||||
resource_name = "Split"
|
resource_name = "Split"
|
||||||
script = ExtResource("2_q5vl6")
|
script = ExtResource("2_rngtv")
|
||||||
direction = 0
|
direction = 0
|
||||||
percent = 0.03125
|
percent = 0.03125
|
||||||
first = SubResource("Resource_12axs")
|
first = SubResource("Resource_12axs")
|
||||||
|
@ -130,7 +144,7 @@ second = SubResource("Resource_af0bk")
|
||||||
|
|
||||||
[sub_resource type="Resource" id="Resource_6dytr"]
|
[sub_resource type="Resource" id="Resource_6dytr"]
|
||||||
resource_name = "Split"
|
resource_name = "Split"
|
||||||
script = ExtResource("2_q5vl6")
|
script = ExtResource("2_rngtv")
|
||||||
direction = 1
|
direction = 1
|
||||||
percent = 0.459538
|
percent = 0.459538
|
||||||
first = SubResource("Resource_otntk")
|
first = SubResource("Resource_otntk")
|
||||||
|
@ -138,12 +152,13 @@ second = SubResource("Resource_1xpva")
|
||||||
|
|
||||||
[resource]
|
[resource]
|
||||||
resource_name = "Tallscreen"
|
resource_name = "Tallscreen"
|
||||||
script = ExtResource("3_ox7l5")
|
script = ExtResource("3_v86xb")
|
||||||
root = SubResource("Resource_6dytr")
|
root = SubResource("Resource_6dytr")
|
||||||
hidden_tabs = {
|
hidden_tabs = {
|
||||||
"Perspective Editor": true,
|
"Perspective Editor": true,
|
||||||
"Recorder": true,
|
"Recorder": true,
|
||||||
"Second Canvas": true
|
"Second Canvas": true,
|
||||||
|
"Tiles": true
|
||||||
}
|
}
|
||||||
windows = {}
|
windows = {}
|
||||||
save_on_change = false
|
save_on_change = false
|
||||||
|
|
|
@ -27,10 +27,6 @@ config/windows_native_icon="res://assets/graphics/icons/icon.ico"
|
||||||
config/ExtensionsAPI_Version=5
|
config/ExtensionsAPI_Version=5
|
||||||
config/Pxo_Version=4
|
config/Pxo_Version=4
|
||||||
|
|
||||||
[audio]
|
|
||||||
|
|
||||||
driver/driver="Dummy"
|
|
||||||
|
|
||||||
[autoload]
|
[autoload]
|
||||||
|
|
||||||
Global="*res://src/Autoload/Global.gd"
|
Global="*res://src/Autoload/Global.gd"
|
||||||
|
@ -689,6 +685,10 @@ adjust_brightness_contrast={
|
||||||
"deadzone": 0.5,
|
"deadzone": 0.5,
|
||||||
"events": []
|
"events": []
|
||||||
}
|
}
|
||||||
|
color_curves={
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": []
|
||||||
|
}
|
||||||
gradient={
|
gradient={
|
||||||
"deadzone": 0.5,
|
"deadzone": 0.5,
|
||||||
"events": []
|
"events": []
|
||||||
|
@ -908,7 +908,7 @@ previous_project={
|
||||||
}
|
}
|
||||||
center_canvas={
|
center_canvas={
|
||||||
"deadzone": 0.5,
|
"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":67,"physical_keycode":0,"key_label":0,"unicode":67,"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":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":66,"physical_keycode":0,"key_label":0,"unicode":66,"location":0,"echo":false,"script":null)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
left_text_tool={
|
left_text_tool={
|
||||||
|
@ -921,6 +921,50 @@ right_text_tool={
|
||||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null)
|
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
show_pixel_indices={
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": []
|
||||||
|
}
|
||||||
|
toggle_draw_tiles_mode={
|
||||||
|
"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":4194306,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
tile_edit_mode_manual={
|
||||||
|
"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":49,"key_label":0,"unicode":33,"location":0,"echo":false,"script":null)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
tile_edit_mode_auto={
|
||||||
|
"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":50,"key_label":0,"unicode":64,"location":0,"echo":false,"script":null)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
tile_edit_mode_stack={
|
||||||
|
"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":51,"key_label":0,"unicode":35,"location":0,"echo":false,"script":null)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
tile_rotate_left={
|
||||||
|
"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,"location":0,"echo":false,"script":null)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
tile_rotate_right={
|
||||||
|
"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":88,"key_label":0,"unicode":88,"location":0,"echo":false,"script":null)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
tile_flip_horizontal={
|
||||||
|
"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,"location":0,"echo":false,"script":null)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
tile_flip_vertical={
|
||||||
|
"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,"location":0,"echo":false,"script":null)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
[input_devices]
|
[input_devices]
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,7 @@ func get_ellipse_points(pos: Vector2i, size: Vector2i) -> Array[Vector2i]:
|
||||||
var y0 := pos.y
|
var y0 := pos.y
|
||||||
var y1 := pos.y + (size.y - 1)
|
var y1 := pos.y + (size.y - 1)
|
||||||
var a := absi(x1 - x0)
|
var a := absi(x1 - x0)
|
||||||
var b := absi(y1 - x0)
|
var b := absi(y1 - y0)
|
||||||
var b1 := b & 1
|
var b1 := b & 1
|
||||||
var dx := 4 * (1 - a) * b * b
|
var dx := 4 * (1 - a) * b * b
|
||||||
var dy := 4 * (b1 + 1) * a * a
|
var dy := 4 * (b1 + 1) * a * a
|
||||||
|
@ -217,7 +217,7 @@ func get_ellipse_points_filled(pos: Vector2i, size: Vector2i, thickness := 1) ->
|
||||||
|
|
||||||
func scale_3x(sprite: Image, tol := 0.196078) -> Image:
|
func scale_3x(sprite: Image, tol := 0.196078) -> Image:
|
||||||
var scaled := Image.create(
|
var scaled := Image.create(
|
||||||
sprite.get_width() * 3, sprite.get_height() * 3, false, Image.FORMAT_RGBA8
|
sprite.get_width() * 3, sprite.get_height() * 3, sprite.has_mipmaps(), sprite.get_format()
|
||||||
)
|
)
|
||||||
var width_minus_one := sprite.get_width() - 1
|
var width_minus_one := sprite.get_width() - 1
|
||||||
var height_minus_one := sprite.get_height() - 1
|
var height_minus_one := sprite.get_height() - 1
|
||||||
|
@ -509,6 +509,8 @@ func similar_colors(c1: Color, c2: Color, tol := 0.392157) -> bool:
|
||||||
func center(indices: Array) -> void:
|
func center(indices: Array) -> void:
|
||||||
var project := Global.current_project
|
var project := Global.current_project
|
||||||
Global.canvas.selection.transform_content_confirm()
|
Global.canvas.selection.transform_content_confirm()
|
||||||
|
var redo_data := {}
|
||||||
|
var undo_data := {}
|
||||||
project.undos += 1
|
project.undos += 1
|
||||||
project.undo_redo.create_action("Center Frames")
|
project.undo_redo.create_action("Center Frames")
|
||||||
for frame in indices:
|
for frame in indices:
|
||||||
|
@ -528,62 +530,88 @@ func center(indices: Array) -> void:
|
||||||
for cel in project.frames[frame].cels:
|
for cel in project.frames[frame].cels:
|
||||||
if not cel is PixelCel:
|
if not cel is PixelCel:
|
||||||
continue
|
continue
|
||||||
var sprite := Image.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8)
|
var cel_image := (cel as PixelCel).get_image()
|
||||||
sprite.blend_rect(cel.image, used_rect, offset)
|
var tmp_centered := project.new_empty_image()
|
||||||
Global.undo_redo_compress_images({cel.image: sprite.data}, {cel.image: cel.image.data})
|
tmp_centered.blend_rect(cel.image, used_rect, offset)
|
||||||
|
var centered := ImageExtended.new()
|
||||||
|
centered.copy_from_custom(tmp_centered, cel_image.is_indexed)
|
||||||
|
if cel is CelTileMap:
|
||||||
|
(cel as CelTileMap).serialize_undo_data_source_image(centered, redo_data, undo_data)
|
||||||
|
centered.add_data_to_dictionary(redo_data, cel_image)
|
||||||
|
cel_image.add_data_to_dictionary(undo_data)
|
||||||
|
project.deserialize_cel_undo_data(redo_data, undo_data)
|
||||||
project.undo_redo.add_undo_method(Global.undo_or_redo.bind(true))
|
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.add_do_method(Global.undo_or_redo.bind(false))
|
||||||
project.undo_redo.commit_action()
|
project.undo_redo.commit_action()
|
||||||
|
|
||||||
|
|
||||||
func scale_image(width: int, height: int, interpolation: int) -> void:
|
func scale_project(width: int, height: int, interpolation: int) -> void:
|
||||||
var redo_data := {}
|
var redo_data := {}
|
||||||
var undo_data := {}
|
var undo_data := {}
|
||||||
for f in Global.current_project.frames:
|
for cel in Global.current_project.get_all_pixel_cels():
|
||||||
for i in range(f.cels.size() - 1, -1, -1):
|
if not cel is PixelCel:
|
||||||
var cel := f.cels[i]
|
continue
|
||||||
if not cel is PixelCel:
|
var cel_image := (cel as PixelCel).get_image()
|
||||||
continue
|
var sprite := _resize_image(cel_image, width, height, interpolation) as ImageExtended
|
||||||
var sprite := Image.new()
|
if cel is CelTileMap:
|
||||||
sprite.copy_from(cel.get_image())
|
(cel as CelTileMap).serialize_undo_data_source_image(sprite, redo_data, undo_data)
|
||||||
if interpolation == Interpolation.SCALE3X:
|
sprite.add_data_to_dictionary(redo_data, cel_image)
|
||||||
var times := Vector2i(
|
cel_image.add_data_to_dictionary(undo_data)
|
||||||
ceili(width / (3.0 * sprite.get_width())),
|
|
||||||
ceili(height / (3.0 * sprite.get_height()))
|
|
||||||
)
|
|
||||||
for _j in range(maxi(times.x, times.y)):
|
|
||||||
sprite.copy_from(scale_3x(sprite))
|
|
||||||
sprite.resize(width, height, Image.INTERPOLATE_NEAREST)
|
|
||||||
elif interpolation == Interpolation.CLEANEDGE:
|
|
||||||
var gen := ShaderImageEffect.new()
|
|
||||||
gen.generate_image(sprite, clean_edge_shader, {}, Vector2i(width, height))
|
|
||||||
elif interpolation == Interpolation.OMNISCALE and omniscale_shader:
|
|
||||||
var gen := ShaderImageEffect.new()
|
|
||||||
gen.generate_image(sprite, omniscale_shader, {}, Vector2i(width, height))
|
|
||||||
else:
|
|
||||||
sprite.resize(width, height, interpolation)
|
|
||||||
redo_data[cel.image] = sprite.data
|
|
||||||
undo_data[cel.image] = cel.image.data
|
|
||||||
|
|
||||||
general_do_and_undo_scale(width, height, redo_data, undo_data)
|
general_do_and_undo_scale(width, height, redo_data, undo_data)
|
||||||
|
|
||||||
|
|
||||||
|
func _resize_image(
|
||||||
|
image: Image, width: int, height: int, interpolation: Image.Interpolation
|
||||||
|
) -> Image:
|
||||||
|
var new_image: Image
|
||||||
|
if image is ImageExtended:
|
||||||
|
new_image = ImageExtended.new()
|
||||||
|
new_image.is_indexed = image.is_indexed
|
||||||
|
new_image.copy_from(image)
|
||||||
|
new_image.select_palette("", false)
|
||||||
|
else:
|
||||||
|
new_image = Image.new()
|
||||||
|
new_image.copy_from(image)
|
||||||
|
if interpolation == Interpolation.SCALE3X:
|
||||||
|
var times := Vector2i(
|
||||||
|
ceili(width / (3.0 * new_image.get_width())),
|
||||||
|
ceili(height / (3.0 * new_image.get_height()))
|
||||||
|
)
|
||||||
|
for _j in range(maxi(times.x, times.y)):
|
||||||
|
new_image.copy_from(scale_3x(new_image))
|
||||||
|
new_image.resize(width, height, Image.INTERPOLATE_NEAREST)
|
||||||
|
elif interpolation == Interpolation.CLEANEDGE:
|
||||||
|
var gen := ShaderImageEffect.new()
|
||||||
|
gen.generate_image(new_image, clean_edge_shader, {}, Vector2i(width, height), false)
|
||||||
|
elif interpolation == Interpolation.OMNISCALE and omniscale_shader:
|
||||||
|
var gen := ShaderImageEffect.new()
|
||||||
|
gen.generate_image(new_image, omniscale_shader, {}, Vector2i(width, height), false)
|
||||||
|
else:
|
||||||
|
new_image.resize(width, height, interpolation)
|
||||||
|
if new_image is ImageExtended:
|
||||||
|
new_image.on_size_changed()
|
||||||
|
return new_image
|
||||||
|
|
||||||
|
|
||||||
## Sets the size of the project to be the same as the size of the active selection.
|
## Sets the size of the project to be the same as the size of the active selection.
|
||||||
func crop_to_selection() -> void:
|
func crop_to_selection() -> void:
|
||||||
if not Global.current_project.has_selection:
|
if not Global.current_project.has_selection:
|
||||||
return
|
return
|
||||||
|
Global.canvas.selection.transform_content_confirm()
|
||||||
var redo_data := {}
|
var redo_data := {}
|
||||||
var undo_data := {}
|
var undo_data := {}
|
||||||
Global.canvas.selection.transform_content_confirm()
|
|
||||||
var rect: Rect2i = Global.canvas.selection.big_bounding_rectangle
|
var rect: Rect2i = Global.canvas.selection.big_bounding_rectangle
|
||||||
# Loop through all the cels to crop them
|
# Loop through all the cels to crop them
|
||||||
for f in Global.current_project.frames:
|
for cel in Global.current_project.get_all_pixel_cels():
|
||||||
for cel in f.cels:
|
var cel_image := cel.get_image()
|
||||||
if not cel is PixelCel:
|
var tmp_cropped := cel_image.get_region(rect)
|
||||||
continue
|
var cropped := ImageExtended.new()
|
||||||
var sprite := cel.get_image().get_region(rect)
|
cropped.copy_from_custom(tmp_cropped, cel_image.is_indexed)
|
||||||
redo_data[cel.image] = sprite.data
|
if cel is CelTileMap:
|
||||||
undo_data[cel.image] = cel.image.data
|
(cel as CelTileMap).serialize_undo_data_source_image(cropped, redo_data, undo_data)
|
||||||
|
cropped.add_data_to_dictionary(redo_data, cel_image)
|
||||||
|
cel_image.add_data_to_dictionary(undo_data)
|
||||||
|
|
||||||
general_do_and_undo_scale(rect.size.x, rect.size.y, redo_data, undo_data)
|
general_do_and_undo_scale(rect.size.x, rect.size.y, redo_data, undo_data)
|
||||||
|
|
||||||
|
@ -593,18 +621,17 @@ func crop_to_selection() -> void:
|
||||||
func crop_to_content() -> void:
|
func crop_to_content() -> void:
|
||||||
Global.canvas.selection.transform_content_confirm()
|
Global.canvas.selection.transform_content_confirm()
|
||||||
var used_rect := Rect2i()
|
var used_rect := Rect2i()
|
||||||
for f in Global.current_project.frames:
|
for cel in Global.current_project.get_all_pixel_cels():
|
||||||
for cel in f.cels:
|
if not cel is PixelCel:
|
||||||
if not cel is PixelCel:
|
continue
|
||||||
continue
|
var cel_used_rect := cel.get_image().get_used_rect()
|
||||||
var cel_used_rect := cel.get_image().get_used_rect()
|
if cel_used_rect == Rect2i(0, 0, 0, 0): # If the cel has no content
|
||||||
if cel_used_rect == Rect2i(0, 0, 0, 0): # If the cel has no content
|
continue
|
||||||
continue
|
|
||||||
|
|
||||||
if used_rect == Rect2i(0, 0, 0, 0): # If we still haven't found the first cel with content
|
if used_rect == Rect2i(0, 0, 0, 0): # If we still haven't found the first cel with content
|
||||||
used_rect = cel_used_rect
|
used_rect = cel_used_rect
|
||||||
else:
|
else:
|
||||||
used_rect = used_rect.merge(cel_used_rect)
|
used_rect = used_rect.merge(cel_used_rect)
|
||||||
|
|
||||||
# If no layer has any content, just return
|
# If no layer has any content, just return
|
||||||
if used_rect == Rect2i(0, 0, 0, 0):
|
if used_rect == Rect2i(0, 0, 0, 0):
|
||||||
|
@ -615,13 +642,15 @@ func crop_to_content() -> void:
|
||||||
var redo_data := {}
|
var redo_data := {}
|
||||||
var undo_data := {}
|
var undo_data := {}
|
||||||
# Loop through all the cels to trim them
|
# Loop through all the cels to trim them
|
||||||
for f in Global.current_project.frames:
|
for cel in Global.current_project.get_all_pixel_cels():
|
||||||
for cel in f.cels:
|
var cel_image := cel.get_image()
|
||||||
if not cel is PixelCel:
|
var tmp_cropped := cel_image.get_region(used_rect)
|
||||||
continue
|
var cropped := ImageExtended.new()
|
||||||
var sprite := cel.get_image().get_region(used_rect)
|
cropped.copy_from_custom(tmp_cropped, cel_image.is_indexed)
|
||||||
redo_data[cel.image] = sprite.data
|
if cel is CelTileMap:
|
||||||
undo_data[cel.image] = cel.image.data
|
(cel as CelTileMap).serialize_undo_data_source_image(cropped, redo_data, undo_data)
|
||||||
|
cropped.add_data_to_dictionary(redo_data, cel_image)
|
||||||
|
cel_image.add_data_to_dictionary(undo_data)
|
||||||
|
|
||||||
general_do_and_undo_scale(width, height, redo_data, undo_data)
|
general_do_and_undo_scale(width, height, redo_data, undo_data)
|
||||||
|
|
||||||
|
@ -629,18 +658,19 @@ func crop_to_content() -> void:
|
||||||
func resize_canvas(width: int, height: int, offset_x: int, offset_y: int) -> void:
|
func resize_canvas(width: int, height: int, offset_x: int, offset_y: int) -> void:
|
||||||
var redo_data := {}
|
var redo_data := {}
|
||||||
var undo_data := {}
|
var undo_data := {}
|
||||||
for f in Global.current_project.frames:
|
for cel in Global.current_project.get_all_pixel_cels():
|
||||||
for cel in f.cels:
|
var cel_image := cel.get_image()
|
||||||
if not cel is PixelCel:
|
var resized := ImageExtended.create_custom(
|
||||||
continue
|
width, height, cel_image.has_mipmaps(), cel_image.get_format(), cel_image.is_indexed
|
||||||
var sprite := Image.create(width, height, false, Image.FORMAT_RGBA8)
|
)
|
||||||
sprite.blend_rect(
|
resized.blend_rect(
|
||||||
cel.get_image(),
|
cel_image, Rect2i(Vector2i.ZERO, cel_image.get_size()), Vector2i(offset_x, offset_y)
|
||||||
Rect2i(Vector2i.ZERO, Global.current_project.size),
|
)
|
||||||
Vector2i(offset_x, offset_y)
|
resized.convert_rgb_to_indexed()
|
||||||
)
|
if cel is CelTileMap:
|
||||||
redo_data[cel.image] = sprite.data
|
(cel as CelTileMap).serialize_undo_data_source_image(resized, redo_data, undo_data)
|
||||||
undo_data[cel.image] = cel.image.data
|
resized.add_data_to_dictionary(redo_data, cel_image)
|
||||||
|
cel_image.add_data_to_dictionary(undo_data)
|
||||||
|
|
||||||
general_do_and_undo_scale(width, height, redo_data, undo_data)
|
general_do_and_undo_scale(width, height, redo_data, undo_data)
|
||||||
|
|
||||||
|
@ -675,7 +705,7 @@ func general_do_and_undo_scale(
|
||||||
project.undo_redo.add_do_property(project, "y_symmetry_point", new_y_symmetry_point)
|
project.undo_redo.add_do_property(project, "y_symmetry_point", new_y_symmetry_point)
|
||||||
project.undo_redo.add_do_property(project.x_symmetry_axis, "points", new_x_symmetry_axis_points)
|
project.undo_redo.add_do_property(project.x_symmetry_axis, "points", new_x_symmetry_axis_points)
|
||||||
project.undo_redo.add_do_property(project.y_symmetry_axis, "points", new_y_symmetry_axis_points)
|
project.undo_redo.add_do_property(project.y_symmetry_axis, "points", new_y_symmetry_axis_points)
|
||||||
Global.undo_redo_compress_images(redo_data, undo_data)
|
project.deserialize_cel_undo_data(redo_data, undo_data)
|
||||||
project.undo_redo.add_undo_property(project, "size", project.size)
|
project.undo_redo.add_undo_property(project, "size", project.size)
|
||||||
project.undo_redo.add_undo_property(project, "x_symmetry_point", project.x_symmetry_point)
|
project.undo_redo.add_undo_property(project, "x_symmetry_point", project.x_symmetry_point)
|
||||||
project.undo_redo.add_undo_property(project, "y_symmetry_point", project.y_symmetry_point)
|
project.undo_redo.add_undo_property(project, "y_symmetry_point", project.y_symmetry_point)
|
||||||
|
|
|
@ -161,7 +161,7 @@ func cache_blended_frames(project := Global.current_project) -> void:
|
||||||
blended_frames.clear()
|
blended_frames.clear()
|
||||||
var frames := _calculate_frames(project)
|
var frames := _calculate_frames(project)
|
||||||
for frame in frames:
|
for frame in frames:
|
||||||
var image := Image.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8)
|
var image := project.new_empty_image()
|
||||||
_blend_layers(image, frame)
|
_blend_layers(image, frame)
|
||||||
blended_frames[frame] = image
|
blended_frames[frame] = image
|
||||||
|
|
||||||
|
@ -208,7 +208,7 @@ func process_spritesheet(project := Global.current_project) -> void:
|
||||||
spritesheet_columns = temp
|
spritesheet_columns = temp
|
||||||
var width := project.size.x * spritesheet_columns
|
var width := project.size.x * spritesheet_columns
|
||||||
var height := project.size.y * spritesheet_rows
|
var height := project.size.y * spritesheet_rows
|
||||||
var whole_image := Image.create(width, height, false, Image.FORMAT_RGBA8)
|
var whole_image := Image.create(width, height, false, project.get_image_format())
|
||||||
var origin := Vector2i.ZERO
|
var origin := Vector2i.ZERO
|
||||||
var hh := 0
|
var hh := 0
|
||||||
var vv := 0
|
var vv := 0
|
||||||
|
@ -282,15 +282,15 @@ func process_animation(project := Global.current_project) -> void:
|
||||||
for cel in frame.cels:
|
for cel in frame.cels:
|
||||||
var image := Image.new()
|
var image := Image.new()
|
||||||
image.copy_from(cel.get_image())
|
image.copy_from(cel.get_image())
|
||||||
var duration := frame.duration * (1.0 / project.fps)
|
var duration := frame.get_duration_in_seconds(project.fps)
|
||||||
processed_images.append(
|
processed_images.append(
|
||||||
ProcessedImage.new(image, project.frames.find(frame), duration)
|
ProcessedImage.new(image, project.frames.find(frame), duration)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
var image := Image.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8)
|
var image := project.new_empty_image()
|
||||||
image.copy_from(blended_frames[frame])
|
image.copy_from(blended_frames[frame])
|
||||||
if erase_unselected_area and project.has_selection:
|
if erase_unselected_area and project.has_selection:
|
||||||
var crop := Image.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8)
|
var crop := project.new_empty_image()
|
||||||
var selection_image = project.selection_map.return_cropped_copy(project.size)
|
var selection_image = project.selection_map.return_cropped_copy(project.size)
|
||||||
crop.blit_rect_mask(
|
crop.blit_rect_mask(
|
||||||
image, selection_image, Rect2i(Vector2i.ZERO, image.get_size()), Vector2i.ZERO
|
image, selection_image, Rect2i(Vector2i.ZERO, image.get_size()), Vector2i.ZERO
|
||||||
|
@ -298,7 +298,7 @@ func process_animation(project := Global.current_project) -> void:
|
||||||
image.copy_from(crop)
|
image.copy_from(crop)
|
||||||
if trim_images:
|
if trim_images:
|
||||||
image = image.get_region(image.get_used_rect())
|
image = image.get_region(image.get_used_rect())
|
||||||
var duration := frame.duration * (1.0 / project.fps)
|
var duration := frame.get_duration_in_seconds(project.fps)
|
||||||
processed_images.append(ProcessedImage.new(image, project.frames.find(frame), duration))
|
processed_images.append(ProcessedImage.new(image, project.frames.find(frame), duration))
|
||||||
|
|
||||||
|
|
||||||
|
@ -325,6 +325,8 @@ func _calculate_frames(project := Global.current_project) -> Array[Frame]:
|
||||||
var inverted_frames := frames.duplicate()
|
var inverted_frames := frames.duplicate()
|
||||||
inverted_frames.reverse()
|
inverted_frames.reverse()
|
||||||
inverted_frames.remove_at(0)
|
inverted_frames.remove_at(0)
|
||||||
|
if inverted_frames.size() > 0:
|
||||||
|
inverted_frames.remove_at(inverted_frames.size() - 1)
|
||||||
frames.append_array(inverted_frames)
|
frames.append_array(inverted_frames)
|
||||||
return frames
|
return frames
|
||||||
|
|
||||||
|
@ -425,7 +427,7 @@ func export_processed_images(
|
||||||
|
|
||||||
if is_single_file_format(project):
|
if is_single_file_format(project):
|
||||||
if is_using_ffmpeg(project.file_format):
|
if is_using_ffmpeg(project.file_format):
|
||||||
var video_exported := export_video(export_paths)
|
var video_exported := export_video(export_paths, project)
|
||||||
if not video_exported:
|
if not video_exported:
|
||||||
Global.popup_error(
|
Global.popup_error(
|
||||||
tr("Video failed to export. Ensure that FFMPEG is installed correctly.")
|
tr("Video failed to export. Ensure that FFMPEG is installed correctly.")
|
||||||
|
@ -503,8 +505,9 @@ func export_processed_images(
|
||||||
|
|
||||||
|
|
||||||
## Uses FFMPEG to export a video
|
## Uses FFMPEG to export a video
|
||||||
func export_video(export_paths: PackedStringArray) -> bool:
|
func export_video(export_paths: PackedStringArray, project: Project) -> bool:
|
||||||
DirAccess.make_dir_absolute(TEMP_PATH)
|
DirAccess.make_dir_absolute(TEMP_PATH)
|
||||||
|
var video_duration := 0
|
||||||
var temp_path_real := ProjectSettings.globalize_path(TEMP_PATH)
|
var temp_path_real := ProjectSettings.globalize_path(TEMP_PATH)
|
||||||
var input_file_path := temp_path_real.path_join("input.txt")
|
var input_file_path := temp_path_real.path_join("input.txt")
|
||||||
var input_file := FileAccess.open(input_file_path, FileAccess.WRITE)
|
var input_file := FileAccess.open(input_file_path, FileAccess.WRITE)
|
||||||
|
@ -514,25 +517,80 @@ func export_video(export_paths: PackedStringArray) -> bool:
|
||||||
processed_images[i].image.save_png(temp_file_path)
|
processed_images[i].image.save_png(temp_file_path)
|
||||||
input_file.store_line("file '" + temp_file_name + "'")
|
input_file.store_line("file '" + temp_file_name + "'")
|
||||||
input_file.store_line("duration %s" % processed_images[i].duration)
|
input_file.store_line("duration %s" % processed_images[i].duration)
|
||||||
|
video_duration += processed_images[i].duration
|
||||||
input_file.close()
|
input_file.close()
|
||||||
|
|
||||||
|
# ffmpeg -y -f concat -i input.txt output_path
|
||||||
var ffmpeg_execute: PackedStringArray = [
|
var ffmpeg_execute: PackedStringArray = [
|
||||||
"-y", "-f", "concat", "-i", input_file_path, export_paths[0]
|
"-y", "-f", "concat", "-i", input_file_path, export_paths[0]
|
||||||
]
|
]
|
||||||
var output := []
|
var success := OS.execute(Global.ffmpeg_path, ffmpeg_execute, [], true)
|
||||||
var success := OS.execute(Global.ffmpeg_path, ffmpeg_execute, output, true)
|
|
||||||
print(output)
|
|
||||||
var temp_dir := DirAccess.open(TEMP_PATH)
|
|
||||||
for file in temp_dir.get_files():
|
|
||||||
temp_dir.remove(file)
|
|
||||||
DirAccess.remove_absolute(TEMP_PATH)
|
|
||||||
if success < 0 or success > 1:
|
if success < 0 or success > 1:
|
||||||
var fail_text := """Video failed to export. Make sure you have FFMPEG installed
|
var fail_text := """Video failed to export. Make sure you have FFMPEG installed
|
||||||
and have set the correct path in the preferences."""
|
and have set the correct path in the preferences."""
|
||||||
Global.popup_error(tr(fail_text))
|
Global.popup_error(tr(fail_text))
|
||||||
|
_clear_temp_folder()
|
||||||
return false
|
return false
|
||||||
|
# Find audio layers
|
||||||
|
var ffmpeg_combine_audio: PackedStringArray = ["-y"]
|
||||||
|
var audio_layer_count := 0
|
||||||
|
var max_audio_duration := 0
|
||||||
|
var adelay_string := ""
|
||||||
|
for layer in project.get_all_audio_layers():
|
||||||
|
if layer.audio is AudioStreamMP3:
|
||||||
|
var temp_file_name := str(audio_layer_count + 1).pad_zeros(number_of_digits) + ".mp3"
|
||||||
|
var temp_file_path := temp_path_real.path_join(temp_file_name)
|
||||||
|
var temp_audio_file := FileAccess.open(temp_file_path, FileAccess.WRITE)
|
||||||
|
temp_audio_file.store_buffer(layer.audio.data)
|
||||||
|
ffmpeg_combine_audio.append("-i")
|
||||||
|
ffmpeg_combine_audio.append(temp_file_path)
|
||||||
|
var delay := floori(layer.playback_position * 1000)
|
||||||
|
# [n]adelay=delay_in_ms:all=1[na]
|
||||||
|
adelay_string += (
|
||||||
|
"[%s]adelay=%s:all=1[%sa];" % [audio_layer_count, delay, audio_layer_count]
|
||||||
|
)
|
||||||
|
audio_layer_count += 1
|
||||||
|
if layer.get_audio_length() >= max_audio_duration:
|
||||||
|
max_audio_duration = layer.get_audio_length()
|
||||||
|
if audio_layer_count > 0:
|
||||||
|
# If we have audio layers, merge them all into one file.
|
||||||
|
for i in audio_layer_count:
|
||||||
|
adelay_string += "[%sa]" % i
|
||||||
|
var amix_inputs_string := "amix=inputs=%s[a]" % audio_layer_count
|
||||||
|
var final_filter_string := adelay_string + amix_inputs_string
|
||||||
|
var audio_file_path := temp_path_real.path_join("audio.mp3")
|
||||||
|
ffmpeg_combine_audio.append_array(
|
||||||
|
PackedStringArray(
|
||||||
|
["-filter_complex", final_filter_string, "-map", '"[a]"', audio_file_path]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# ffmpeg -i input1 -i input2 ... -i inputn -filter_complex amix=inputs=n output_path
|
||||||
|
var combined_audio_success := OS.execute(Global.ffmpeg_path, ffmpeg_combine_audio, [], true)
|
||||||
|
if combined_audio_success == 0 or combined_audio_success == 1:
|
||||||
|
var copied_video := temp_path_real.path_join("video." + export_paths[0].get_extension())
|
||||||
|
# Then mix the audio file with the video.
|
||||||
|
DirAccess.copy_absolute(export_paths[0], copied_video)
|
||||||
|
# ffmpeg -y -i video_file -i input_audio -c:v copy -map 0:v:0 -map 1:a:0 video_file
|
||||||
|
var ffmpeg_final_video: PackedStringArray = [
|
||||||
|
"-y", "-i", copied_video, "-i", audio_file_path
|
||||||
|
]
|
||||||
|
if max_audio_duration > video_duration:
|
||||||
|
ffmpeg_final_video.append("-shortest")
|
||||||
|
ffmpeg_final_video.append_array(
|
||||||
|
["-c:v", "copy", "-map", "0:v:0", "-map", "1:a:0", export_paths[0]]
|
||||||
|
)
|
||||||
|
OS.execute(Global.ffmpeg_path, ffmpeg_final_video, [], true)
|
||||||
|
_clear_temp_folder()
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
|
||||||
|
func _clear_temp_folder() -> void:
|
||||||
|
var temp_dir := DirAccess.open(TEMP_PATH)
|
||||||
|
for file in temp_dir.get_files():
|
||||||
|
temp_dir.remove(file)
|
||||||
|
DirAccess.remove_absolute(TEMP_PATH)
|
||||||
|
|
||||||
|
|
||||||
func export_animated(args: Dictionary) -> void:
|
func export_animated(args: Dictionary) -> void:
|
||||||
var project: Project = args["project"]
|
var project: Project = args["project"]
|
||||||
var exporter: AImgIOBaseExporter = args["exporter"]
|
var exporter: AImgIOBaseExporter = args["exporter"]
|
||||||
|
|
|
@ -168,11 +168,11 @@ class GeneralAPI:
|
||||||
|
|
||||||
## Returns a new ValueSliderV2. Useful for editing 2D vectors.
|
## Returns a new ValueSliderV2. Useful for editing 2D vectors.
|
||||||
func create_value_slider_v2() -> ValueSliderV2:
|
func create_value_slider_v2() -> ValueSliderV2:
|
||||||
return preload("res://src/UI/Nodes/ValueSliderV2.tscn").instantiate()
|
return preload("res://src/UI/Nodes/Sliders/ValueSliderV2.tscn").instantiate()
|
||||||
|
|
||||||
## Returns a new ValueSliderV3. Useful for editing 3D vectors.
|
## Returns a new ValueSliderV3. Useful for editing 3D vectors.
|
||||||
func create_value_slider_v3() -> ValueSliderV3:
|
func create_value_slider_v3() -> ValueSliderV3:
|
||||||
return preload("res://src/UI/Nodes/ValueSliderV3.tscn").instantiate()
|
return preload("res://src/UI/Nodes/Sliders/ValueSliderV3.tscn").instantiate()
|
||||||
|
|
||||||
|
|
||||||
## Gives ability to add/remove items from menus in the top bar.
|
## Gives ability to add/remove items from menus in the top bar.
|
||||||
|
@ -631,7 +631,7 @@ class ProjectAPI:
|
||||||
|
|
||||||
## Returns the current cel.
|
## Returns the current cel.
|
||||||
## Cel type can be checked using function [method get_class_name] inside the cel
|
## Cel type can be checked using function [method get_class_name] inside the cel
|
||||||
## type can be GroupCel, PixelCel, Cel3D, or BaseCel.
|
## type can be GroupCel, PixelCel, Cel3D, CelTileMap, AudioCel or BaseCel.
|
||||||
func get_current_cel() -> BaseCel:
|
func get_current_cel() -> BaseCel:
|
||||||
return current_project.get_current_cel()
|
return current_project.get_current_cel()
|
||||||
|
|
||||||
|
@ -896,7 +896,7 @@ class SignalsAPI:
|
||||||
# TOOL RELATED SIGNALS
|
# TOOL RELATED SIGNALS
|
||||||
## Connects/disconnects a signal to [param callable], that emits
|
## Connects/disconnects a signal to [param callable], that emits
|
||||||
## whenever a tool changes color.[br]
|
## whenever a tool changes color.[br]
|
||||||
## [b]Binds: [/b] It has two bind of type [Color] (indicating new color)
|
## [b]Binds: [/b] It has two bind of type [Color] (a dictionary with keys "color" and "index")
|
||||||
## and [int] (Indicating button that tool is assigned to, see [enum @GlobalScope.MouseButton])
|
## and [int] (Indicating button that tool is assigned to, see [enum @GlobalScope.MouseButton])
|
||||||
func signal_tool_color_changed(callable: Callable, is_disconnecting := false) -> void:
|
func signal_tool_color_changed(callable: Callable, is_disconnecting := false) -> void:
|
||||||
_connect_disconnect(Tools.color_changed, callable, is_disconnecting)
|
_connect_disconnect(Tools.color_changed, callable, is_disconnecting)
|
||||||
|
|
|
@ -14,7 +14,7 @@ signal cel_switched ## Emitted whenever you select a different cel.
|
||||||
signal project_data_changed(project: Project) ## Emitted when project data is modified.
|
signal project_data_changed(project: Project) ## Emitted when project data is modified.
|
||||||
signal font_loaded ## Emitted when a new font has been loaded, or an old one gets unloaded.
|
signal font_loaded ## Emitted when a new font has been loaded, or an old one gets unloaded.
|
||||||
|
|
||||||
enum LayerTypes { PIXEL, GROUP, THREE_D }
|
enum LayerTypes { PIXEL, GROUP, THREE_D, TILEMAP, AUDIO }
|
||||||
enum GridTypes { CARTESIAN, ISOMETRIC, ALL }
|
enum GridTypes { CARTESIAN, ISOMETRIC, ALL }
|
||||||
## ## Used to tell whether a color is being taken from the current theme,
|
## ## Used to tell whether a color is being taken from the current theme,
|
||||||
## or if it is a custom color.
|
## or if it is a custom color.
|
||||||
|
@ -35,6 +35,7 @@ enum ViewMenu {
|
||||||
MIRROR_VIEW,
|
MIRROR_VIEW,
|
||||||
SHOW_GRID,
|
SHOW_GRID,
|
||||||
SHOW_PIXEL_GRID,
|
SHOW_PIXEL_GRID,
|
||||||
|
SHOW_PIXEL_INDICES,
|
||||||
SHOW_RULERS,
|
SHOW_RULERS,
|
||||||
SHOW_GUIDES,
|
SHOW_GUIDES,
|
||||||
SHOW_MOUSE_GUIDES,
|
SHOW_MOUSE_GUIDES,
|
||||||
|
@ -46,6 +47,7 @@ enum WindowMenu { WINDOW_OPACITY, PANELS, LAYOUTS, MOVABLE_PANELS, ZEN_MODE, FUL
|
||||||
## Enumeration of items present in the Image Menu.
|
## Enumeration of items present in the Image Menu.
|
||||||
enum ImageMenu {
|
enum ImageMenu {
|
||||||
PROJECT_PROPERTIES,
|
PROJECT_PROPERTIES,
|
||||||
|
COLOR_MODE,
|
||||||
RESIZE_CANVAS,
|
RESIZE_CANVAS,
|
||||||
SCALE_IMAGE,
|
SCALE_IMAGE,
|
||||||
CROP_TO_SELECTION,
|
CROP_TO_SELECTION,
|
||||||
|
@ -62,16 +64,17 @@ enum EffectsMenu {
|
||||||
DESATURATION,
|
DESATURATION,
|
||||||
HSV,
|
HSV,
|
||||||
BRIGHTNESS_SATURATION,
|
BRIGHTNESS_SATURATION,
|
||||||
|
COLOR_CURVES,
|
||||||
PALETTIZE,
|
PALETTIZE,
|
||||||
PIXELIZE,
|
PIXELIZE,
|
||||||
POSTERIZE,
|
POSTERIZE,
|
||||||
GAUSSIAN_BLUR,
|
GAUSSIAN_BLUR,
|
||||||
GRADIENT,
|
GRADIENT,
|
||||||
GRADIENT_MAP,
|
GRADIENT_MAP,
|
||||||
SHADER
|
LOADED_EFFECTS
|
||||||
}
|
}
|
||||||
## Enumeration of items present in the Select Menu.
|
## Enumeration of items present in the Select Menu.
|
||||||
enum SelectMenu { SELECT_ALL, CLEAR_SELECTION, INVERT, TILE_MODE, MODIFY }
|
enum SelectMenu { SELECT_ALL, CLEAR_SELECTION, INVERT, WRAP_STROKES, MODIFY }
|
||||||
## Enumeration of items present in the Help Menu.
|
## Enumeration of items present in the Help Menu.
|
||||||
enum HelpMenu {
|
enum HelpMenu {
|
||||||
VIEW_SPLASH_SCREEN,
|
VIEW_SPLASH_SCREEN,
|
||||||
|
@ -178,10 +181,14 @@ var can_draw := true
|
||||||
var move_guides_on_canvas := true
|
var move_guides_on_canvas := true
|
||||||
|
|
||||||
var play_only_tags := true ## If [code]true[/code], animation plays only on frames of the same tag.
|
var play_only_tags := true ## If [code]true[/code], animation plays only on frames of the same tag.
|
||||||
## (Intended to be used as getter only) Tells if the x-symmetry guide ( -- ) is visible.
|
## If true, the x symmetry guide ( -- ) is visible.
|
||||||
var show_x_symmetry_axis := false
|
var show_x_symmetry_axis := false
|
||||||
## (Intended to be used as getter only) Tells if the y-symmetry guide ( | ) is visible.
|
## If true, the y symmetry guide ( | ) is visible.
|
||||||
var show_y_symmetry_axis := false
|
var show_y_symmetry_axis := false
|
||||||
|
## If true, the x=y symmetry guide ( / ) is visible.
|
||||||
|
var show_xy_symmetry_axis := false
|
||||||
|
## If true, the x==y symmetry guide ( \ ) is visible.
|
||||||
|
var show_x_minus_y_symmetry_axis := false
|
||||||
|
|
||||||
# Preferences
|
# Preferences
|
||||||
## Found in Preferences. If [code]true[/code], the last saved project will open on startup.
|
## Found in Preferences. If [code]true[/code], the last saved project will open on startup.
|
||||||
|
@ -332,55 +339,8 @@ var default_height := 64 ## Found in Preferences. The default height of startup
|
||||||
var default_fill_color := Color(0, 0, 0, 0)
|
var default_fill_color := Color(0, 0, 0, 0)
|
||||||
## Found in Preferences. The distance to the guide or grig below which cursor snapping activates.
|
## Found in Preferences. The distance to the guide or grig below which cursor snapping activates.
|
||||||
var snapping_distance := 32.0
|
var snapping_distance := 32.0
|
||||||
## Found in Preferences. The grid type defined by [enum GridTypes] enum.
|
## Contains dictionaries of individual grids.
|
||||||
var grid_type := GridTypes.CARTESIAN:
|
var grids: Array[Grid] = []
|
||||||
set(value):
|
|
||||||
if value == grid_type:
|
|
||||||
return
|
|
||||||
grid_type = value
|
|
||||||
if is_instance_valid(canvas.grid):
|
|
||||||
canvas.grid.queue_redraw()
|
|
||||||
## Found in Preferences. The size of rectangular grid.
|
|
||||||
var grid_size := Vector2i(2, 2):
|
|
||||||
set(value):
|
|
||||||
if value == grid_size:
|
|
||||||
return
|
|
||||||
grid_size = value
|
|
||||||
if is_instance_valid(canvas.grid):
|
|
||||||
canvas.grid.queue_redraw()
|
|
||||||
## Found in Preferences. The size of isometric grid.
|
|
||||||
var isometric_grid_size := Vector2i(16, 8):
|
|
||||||
set(value):
|
|
||||||
if value == isometric_grid_size:
|
|
||||||
return
|
|
||||||
isometric_grid_size = value
|
|
||||||
if is_instance_valid(canvas.grid):
|
|
||||||
canvas.grid.queue_redraw()
|
|
||||||
## Found in Preferences. The grid offset from top-left corner of the canvas.
|
|
||||||
var grid_offset := Vector2i.ZERO:
|
|
||||||
set(value):
|
|
||||||
if value == grid_offset:
|
|
||||||
return
|
|
||||||
grid_offset = value
|
|
||||||
if is_instance_valid(canvas.grid):
|
|
||||||
canvas.grid.queue_redraw()
|
|
||||||
## Found in Preferences. If [code]true[/code], The grid draws over the area extended by
|
|
||||||
## tile-mode as well.
|
|
||||||
var grid_draw_over_tile_mode := false:
|
|
||||||
set(value):
|
|
||||||
if value == grid_draw_over_tile_mode:
|
|
||||||
return
|
|
||||||
grid_draw_over_tile_mode = value
|
|
||||||
if is_instance_valid(canvas.grid):
|
|
||||||
canvas.grid.queue_redraw()
|
|
||||||
## Found in Preferences. The color of grid.
|
|
||||||
var grid_color := Color.BLACK:
|
|
||||||
set(value):
|
|
||||||
if value == grid_color:
|
|
||||||
return
|
|
||||||
grid_color = value
|
|
||||||
if is_instance_valid(canvas.grid):
|
|
||||||
canvas.grid.queue_redraw()
|
|
||||||
## Found in Preferences. The minimum zoom after which pixel grid gets drawn if enabled.
|
## Found in Preferences. The minimum zoom after which pixel grid gets drawn if enabled.
|
||||||
var pixel_grid_show_at_zoom := 1500.0: # percentage
|
var pixel_grid_show_at_zoom := 1500.0: # percentage
|
||||||
set(value):
|
set(value):
|
||||||
|
@ -531,6 +491,11 @@ var window_transparency := false:
|
||||||
return
|
return
|
||||||
window_transparency = value
|
window_transparency = value
|
||||||
_save_to_override_file()
|
_save_to_override_file()
|
||||||
|
var dummy_audio_driver := false:
|
||||||
|
set(value):
|
||||||
|
if value != dummy_audio_driver:
|
||||||
|
dummy_audio_driver = value
|
||||||
|
_save_to_override_file()
|
||||||
|
|
||||||
## Found in Preferences. The time (in minutes) after which backup is created (if enabled).
|
## Found in Preferences. The time (in minutes) after which backup is created (if enabled).
|
||||||
var autosave_interval := 1.0:
|
var autosave_interval := 1.0:
|
||||||
|
@ -597,6 +562,12 @@ var show_rulers := true:
|
||||||
var show_guides := true
|
var show_guides := true
|
||||||
## If [code]true[/code], the mouse guides are visible.
|
## If [code]true[/code], the mouse guides are visible.
|
||||||
var show_mouse_guides := false
|
var show_mouse_guides := false
|
||||||
|
## If [code]true[/code], the indices of color are shown.
|
||||||
|
var show_pixel_indices := false:
|
||||||
|
set(value):
|
||||||
|
show_pixel_indices = value
|
||||||
|
if is_instance_valid(canvas.color_index):
|
||||||
|
canvas.color_index.enabled = value
|
||||||
var display_layer_effects := true:
|
var display_layer_effects := true:
|
||||||
set(value):
|
set(value):
|
||||||
if value == display_layer_effects:
|
if value == display_layer_effects:
|
||||||
|
@ -672,6 +643,62 @@ var cel_button_scene: PackedScene = load("res://src/UI/Timeline/CelButton.tscn")
|
||||||
@onready var error_dialog: AcceptDialog = control.find_child("ErrorDialog")
|
@onready var error_dialog: AcceptDialog = control.find_child("ErrorDialog")
|
||||||
|
|
||||||
|
|
||||||
|
class Grid:
|
||||||
|
var grid_type := GridTypes.CARTESIAN:
|
||||||
|
set(value):
|
||||||
|
if value == grid_type:
|
||||||
|
return
|
||||||
|
grid_type = value
|
||||||
|
if is_instance_valid(Global.canvas.grid):
|
||||||
|
Global.canvas.grid.queue_redraw()
|
||||||
|
## Found in Preferences. The size of rectangular grid.
|
||||||
|
var grid_size := Vector2i(2, 2):
|
||||||
|
set(value):
|
||||||
|
if value == grid_size:
|
||||||
|
return
|
||||||
|
grid_size = value
|
||||||
|
if is_instance_valid(Global.canvas.grid):
|
||||||
|
Global.canvas.grid.queue_redraw()
|
||||||
|
## Found in Preferences. The size of isometric grid.
|
||||||
|
var isometric_grid_size := Vector2i(16, 8):
|
||||||
|
set(value):
|
||||||
|
if value == isometric_grid_size:
|
||||||
|
return
|
||||||
|
isometric_grid_size = value
|
||||||
|
if is_instance_valid(Global.canvas.grid):
|
||||||
|
Global.canvas.grid.queue_redraw()
|
||||||
|
## Found in Preferences. The grid offset from top-left corner of the canvas.
|
||||||
|
var grid_offset := Vector2i.ZERO:
|
||||||
|
set(value):
|
||||||
|
if value == grid_offset:
|
||||||
|
return
|
||||||
|
grid_offset = value
|
||||||
|
if is_instance_valid(Global.canvas.grid):
|
||||||
|
Global.canvas.grid.queue_redraw()
|
||||||
|
## Found in Preferences. If [code]true[/code], The grid draws over the area extended by
|
||||||
|
## tile-mode as well.
|
||||||
|
var grid_draw_over_tile_mode := false:
|
||||||
|
set(value):
|
||||||
|
if value == grid_draw_over_tile_mode:
|
||||||
|
return
|
||||||
|
grid_draw_over_tile_mode = value
|
||||||
|
if is_instance_valid(Global.canvas.grid):
|
||||||
|
Global.canvas.grid.queue_redraw()
|
||||||
|
## Found in Preferences. The color of grid.
|
||||||
|
var grid_color := Color.BLACK:
|
||||||
|
set(value):
|
||||||
|
if value == grid_color:
|
||||||
|
return
|
||||||
|
grid_color = value
|
||||||
|
if is_instance_valid(Global.canvas.grid):
|
||||||
|
Global.canvas.grid.queue_redraw()
|
||||||
|
|
||||||
|
func _init(properties := {}) -> void:
|
||||||
|
Global.grids.append(self)
|
||||||
|
for prop in properties.keys():
|
||||||
|
set(prop, properties[prop])
|
||||||
|
|
||||||
|
|
||||||
func _init() -> void:
|
func _init() -> void:
|
||||||
# Load settings from the config file
|
# Load settings from the config file
|
||||||
config_cache.load(CONFIG_PATH)
|
config_cache.load(CONFIG_PATH)
|
||||||
|
@ -705,9 +732,12 @@ func _init() -> void:
|
||||||
window_transparency = ProjectSettings.get_setting(
|
window_transparency = ProjectSettings.get_setting(
|
||||||
"display/window/per_pixel_transparency/allowed"
|
"display/window/per_pixel_transparency/allowed"
|
||||||
)
|
)
|
||||||
|
dummy_audio_driver = ProjectSettings.get_setting("audio/driver/driver") == "Dummy"
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
|
# Initialize Grid
|
||||||
|
Grid.new() # gets auto added to grids array
|
||||||
_initialize_keychain()
|
_initialize_keychain()
|
||||||
default_width = config_cache.get_value("preferences", "default_width", default_width)
|
default_width = config_cache.get_value("preferences", "default_width", default_width)
|
||||||
default_height = config_cache.get_value("preferences", "default_height", default_height)
|
default_height = config_cache.get_value("preferences", "default_height", default_height)
|
||||||
|
@ -724,11 +754,26 @@ func _ready() -> void:
|
||||||
if get(pref) == null:
|
if get(pref) == null:
|
||||||
continue
|
continue
|
||||||
var value = config_cache.get_value("preferences", pref)
|
var value = config_cache.get_value("preferences", pref)
|
||||||
set(pref, value)
|
if pref == "grids":
|
||||||
|
if value:
|
||||||
|
update_grids(value)
|
||||||
|
else:
|
||||||
|
set(pref, value)
|
||||||
if OS.is_sandboxed():
|
if OS.is_sandboxed():
|
||||||
Global.use_native_file_dialogs = true
|
Global.use_native_file_dialogs = true
|
||||||
await get_tree().process_frame
|
await get_tree().process_frame
|
||||||
project_switched.emit()
|
project_switched.emit()
|
||||||
|
canvas.color_index.enabled = show_pixel_indices # Initialize color index preview
|
||||||
|
|
||||||
|
|
||||||
|
func update_grids(grids_data: Dictionary):
|
||||||
|
# Remove old grids
|
||||||
|
grids.clear()
|
||||||
|
if is_instance_valid(Global.canvas.grid):
|
||||||
|
Global.canvas.grid.queue_redraw()
|
||||||
|
# ADD new ones
|
||||||
|
for grid_idx in grids_data.size():
|
||||||
|
Grid.new(grids_data[grid_idx]) # gets auto added to grids array
|
||||||
|
|
||||||
|
|
||||||
func _initialize_keychain() -> void:
|
func _initialize_keychain() -> void:
|
||||||
|
@ -765,6 +810,7 @@ func _initialize_keychain() -> void:
|
||||||
&"drop_shadow": Keychain.InputAction.new("", "Effects menu", true),
|
&"drop_shadow": Keychain.InputAction.new("", "Effects menu", true),
|
||||||
&"adjust_hsv": Keychain.InputAction.new("", "Effects menu", true),
|
&"adjust_hsv": Keychain.InputAction.new("", "Effects menu", true),
|
||||||
&"adjust_brightness_contrast": Keychain.InputAction.new("", "Effects menu", true),
|
&"adjust_brightness_contrast": Keychain.InputAction.new("", "Effects menu", true),
|
||||||
|
&"color_curves": Keychain.InputAction.new("", "Effects menu", true),
|
||||||
&"gaussian_blur": Keychain.InputAction.new("", "Effects menu", true),
|
&"gaussian_blur": Keychain.InputAction.new("", "Effects menu", true),
|
||||||
&"gradient": Keychain.InputAction.new("", "Effects menu", true),
|
&"gradient": Keychain.InputAction.new("", "Effects menu", true),
|
||||||
&"gradient_map": Keychain.InputAction.new("", "Effects menu", true),
|
&"gradient_map": Keychain.InputAction.new("", "Effects menu", true),
|
||||||
|
@ -859,12 +905,17 @@ func _initialize_keychain() -> void:
|
||||||
&"reference_rotate": Keychain.InputAction.new("", "Reference images", false),
|
&"reference_rotate": Keychain.InputAction.new("", "Reference images", false),
|
||||||
&"reference_scale": Keychain.InputAction.new("", "Reference images", false),
|
&"reference_scale": Keychain.InputAction.new("", "Reference images", false),
|
||||||
&"reference_quick_menu": Keychain.InputAction.new("", "Reference images", false),
|
&"reference_quick_menu": Keychain.InputAction.new("", "Reference images", false),
|
||||||
&"cancel_reference_transform": Keychain.InputAction.new("", "Reference images", false)
|
&"cancel_reference_transform": Keychain.InputAction.new("", "Reference images", false),
|
||||||
|
&"tile_rotate_left": Keychain.InputAction.new("", "Tileset panel", false),
|
||||||
|
&"tile_rotate_right": Keychain.InputAction.new("", "Tileset panel", false),
|
||||||
|
&"tile_flip_horizontal": Keychain.InputAction.new("", "Tileset panel", false),
|
||||||
|
&"tile_flip_vertical": Keychain.InputAction.new("", "Tileset panel", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
Keychain.groups = {
|
Keychain.groups = {
|
||||||
"Canvas": Keychain.InputGroup.new("", false),
|
"Canvas": Keychain.InputGroup.new("", false),
|
||||||
"Cursor movement": Keychain.InputGroup.new("Canvas"),
|
"Cursor movement": Keychain.InputGroup.new("Canvas"),
|
||||||
|
"Reference images": Keychain.InputGroup.new("Canvas"),
|
||||||
"Buttons": Keychain.InputGroup.new(),
|
"Buttons": Keychain.InputGroup.new(),
|
||||||
"Tools": Keychain.InputGroup.new(),
|
"Tools": Keychain.InputGroup.new(),
|
||||||
"Left": Keychain.InputGroup.new("Tools"),
|
"Left": Keychain.InputGroup.new("Tools"),
|
||||||
|
@ -883,7 +934,7 @@ func _initialize_keychain() -> void:
|
||||||
"Shape tools": Keychain.InputGroup.new("Tool modifiers"),
|
"Shape tools": Keychain.InputGroup.new("Tool modifiers"),
|
||||||
"Selection tools": Keychain.InputGroup.new("Tool modifiers"),
|
"Selection tools": Keychain.InputGroup.new("Tool modifiers"),
|
||||||
"Transformation tools": Keychain.InputGroup.new("Tool modifiers"),
|
"Transformation tools": Keychain.InputGroup.new("Tool modifiers"),
|
||||||
"Reference images": Keychain.InputGroup.new("Canvas")
|
"Tileset panel": Keychain.InputGroup.new()
|
||||||
}
|
}
|
||||||
Keychain.ignore_actions = ["left_mouse", "right_mouse", "middle_mouse", "shift", "ctrl"]
|
Keychain.ignore_actions = ["left_mouse", "right_mouse", "middle_mouse", "shift", "ctrl"]
|
||||||
|
|
||||||
|
@ -916,7 +967,7 @@ func general_redo(project := current_project) -> void:
|
||||||
## Performs actions done after an undo or redo is done. this takes [member general_undo] and
|
## Performs actions done after an undo or redo is done. this takes [member general_undo] and
|
||||||
## [member general_redo] a step further. Does further work if the current action requires it
|
## [member general_redo] a step further. Does further work if the current action requires it
|
||||||
## like refreshing textures, redraw UI elements etc...[br]
|
## like refreshing textures, redraw UI elements etc...[br]
|
||||||
## [param frame_index] and [param layer_index] are there for optimizzation. if the undo or redo
|
## [param frame_index] and [param layer_index] are there for optimization. if the undo or redo
|
||||||
## happens only in one cel then the cel's frame and layer should be passed to [param frame_index]
|
## happens only in one cel then the cel's frame and layer should be passed to [param frame_index]
|
||||||
## and [param layer_index] respectively, otherwise the entire timeline will be refreshed.
|
## and [param layer_index] respectively, otherwise the entire timeline will be refreshed.
|
||||||
func undo_or_redo(
|
func undo_or_redo(
|
||||||
|
@ -942,20 +993,24 @@ func undo_or_redo(
|
||||||
]
|
]
|
||||||
):
|
):
|
||||||
if layer_index > -1 and frame_index > -1:
|
if layer_index > -1 and frame_index > -1:
|
||||||
canvas.update_texture(layer_index, frame_index, project)
|
var cel := project.frames[frame_index].cels[layer_index]
|
||||||
|
if action_name == "Scale":
|
||||||
|
cel.size_changed(project.size)
|
||||||
|
canvas.update_texture(layer_index, frame_index, project, undo)
|
||||||
else:
|
else:
|
||||||
for i in project.frames.size():
|
for i in project.frames.size():
|
||||||
for j in project.layers.size():
|
for j in project.layers.size():
|
||||||
canvas.update_texture(j, i, project)
|
var cel := project.frames[i].cels[j]
|
||||||
|
if action_name == "Scale":
|
||||||
|
cel.size_changed(project.size)
|
||||||
|
canvas.update_texture(j, i, project, undo)
|
||||||
|
|
||||||
canvas.selection.queue_redraw()
|
canvas.selection.queue_redraw()
|
||||||
if action_name == "Scale":
|
if action_name == "Scale":
|
||||||
for i in project.frames.size():
|
for i in project.frames.size():
|
||||||
for j in project.layers.size():
|
for j in project.layers.size():
|
||||||
var current_cel := project.frames[i].cels[j]
|
var current_cel := project.frames[i].cels[j]
|
||||||
if current_cel is Cel3D:
|
if current_cel is not Cel3D:
|
||||||
current_cel.size_changed(project.size)
|
|
||||||
else:
|
|
||||||
current_cel.image_texture.set_image(current_cel.get_image())
|
current_cel.image_texture.set_image(current_cel.get_image())
|
||||||
canvas.camera_zoom()
|
canvas.camera_zoom()
|
||||||
canvas.grid.queue_redraw()
|
canvas.grid.queue_redraw()
|
||||||
|
@ -1061,7 +1116,9 @@ func get_available_font_names() -> PackedStringArray:
|
||||||
if font_name in font_names:
|
if font_name in font_names:
|
||||||
continue
|
continue
|
||||||
font_names.append(font_name)
|
font_names.append(font_name)
|
||||||
for system_font_name in OS.get_system_fonts():
|
var system_fonts := OS.get_system_fonts()
|
||||||
|
system_fonts.sort()
|
||||||
|
for system_font_name in system_fonts:
|
||||||
if system_font_name in font_names:
|
if system_font_name in font_names:
|
||||||
continue
|
continue
|
||||||
font_names.append(system_font_name)
|
font_names.append(system_font_name)
|
||||||
|
@ -1113,8 +1170,17 @@ func undo_redo_compress_images(
|
||||||
func undo_redo_draw_op(
|
func undo_redo_draw_op(
|
||||||
image: Image, new_size: Vector2i, compressed_image_data: PackedByteArray, buffer_size: int
|
image: Image, new_size: Vector2i, compressed_image_data: PackedByteArray, buffer_size: int
|
||||||
) -> void:
|
) -> void:
|
||||||
var decompressed := compressed_image_data.decompress(buffer_size)
|
if image is ImageExtended and image.is_indexed:
|
||||||
image.set_data(new_size.x, new_size.y, image.has_mipmaps(), image.get_format(), decompressed)
|
# If using indexed mode,
|
||||||
|
# just convert the indices to RGB instead of setting the image data directly.
|
||||||
|
if image.get_size() != new_size:
|
||||||
|
image.crop(new_size.x, new_size.y)
|
||||||
|
image.convert_indexed_to_rgb()
|
||||||
|
else:
|
||||||
|
var decompressed := compressed_image_data.decompress(buffer_size)
|
||||||
|
image.set_data(
|
||||||
|
new_size.x, new_size.y, image.has_mipmaps(), image.get_format(), decompressed
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
## This method is used to write project setting overrides to the override.cfg file, located
|
## This method is used to write project setting overrides to the override.cfg file, located
|
||||||
|
@ -1129,3 +1195,6 @@ func _save_to_override_file() -> void:
|
||||||
file.store_line("[display]\n")
|
file.store_line("[display]\n")
|
||||||
file.store_line("window/subwindows/embed_subwindows=%s" % single_window_mode)
|
file.store_line("window/subwindows/embed_subwindows=%s" % single_window_mode)
|
||||||
file.store_line("window/per_pixel_transparency/allowed=%s" % window_transparency)
|
file.store_line("window/per_pixel_transparency/allowed=%s" % window_transparency)
|
||||||
|
if dummy_audio_driver:
|
||||||
|
file.store_line("[audio]\n")
|
||||||
|
file.store_line('driver/driver="Dummy"')
|
||||||
|
|
|
@ -90,9 +90,9 @@ func get_brush_files_from_directory(directory: String): # -> Array
|
||||||
func add_randomised_brush(fpaths: Array, tooltip_name: String) -> void:
|
func add_randomised_brush(fpaths: Array, tooltip_name: String) -> void:
|
||||||
# Attempt to load the images from the file paths.
|
# Attempt to load the images from the file paths.
|
||||||
var loaded_images: Array = []
|
var loaded_images: Array = []
|
||||||
for filen in fpaths:
|
for file in fpaths:
|
||||||
var image := Image.new()
|
var image := Image.new()
|
||||||
var err := image.load(filen)
|
var err := image.load(file)
|
||||||
if err == OK:
|
if err == OK:
|
||||||
image.convert(Image.FORMAT_RGBA8)
|
image.convert(Image.FORMAT_RGBA8)
|
||||||
loaded_images.append(image)
|
loaded_images.append(image)
|
||||||
|
|
|
@ -3,6 +3,9 @@ extends Node
|
||||||
|
|
||||||
signal project_saved
|
signal project_saved
|
||||||
signal reference_image_imported
|
signal reference_image_imported
|
||||||
|
signal shader_copied(file_path: String)
|
||||||
|
|
||||||
|
const SHADERS_DIRECTORY := "user://shaders"
|
||||||
|
|
||||||
var preview_dialog_tscn := preload("res://src/UI/Dialogs/ImportPreviewDialog.tscn")
|
var preview_dialog_tscn := preload("res://src/UI/Dialogs/ImportPreviewDialog.tscn")
|
||||||
var preview_dialogs := [] ## Array of preview dialogs
|
var preview_dialogs := [] ## Array of preview dialogs
|
||||||
|
@ -39,12 +42,15 @@ func handle_loading_file(file: String) -> void:
|
||||||
elif file_ext in ["pck", "zip"]: # Godot resource pack file
|
elif file_ext in ["pck", "zip"]: # Godot resource pack file
|
||||||
Global.control.get_node("Extensions").install_extension(file)
|
Global.control.get_node("Extensions").install_extension(file)
|
||||||
|
|
||||||
elif file_ext == "shader" or file_ext == "gdshader": # Godot shader file
|
elif file_ext == "gdshader": # Godot shader file
|
||||||
var shader := load(file)
|
var shader := load(file)
|
||||||
if not shader is Shader:
|
if not shader is Shader:
|
||||||
return
|
return
|
||||||
var file_name: String = file.get_file().get_basename()
|
var new_path := SHADERS_DIRECTORY.path_join(file.get_file())
|
||||||
Global.control.find_child("ShaderEffect").change_shader(shader, file_name)
|
DirAccess.copy_absolute(file, new_path)
|
||||||
|
shader_copied.emit(new_path)
|
||||||
|
elif file_ext == "mp3": # Audio file
|
||||||
|
open_audio_file(file)
|
||||||
|
|
||||||
else: # Image files
|
else: # Image files
|
||||||
# Attempt to load as APNG.
|
# Attempt to load as APNG.
|
||||||
|
@ -150,7 +156,7 @@ func handle_loading_aimg(path: String, frames: Array) -> void:
|
||||||
if not frames_agree:
|
if not frames_agree:
|
||||||
frame.duration = aimg_frame.duration * project.fps
|
frame.duration = aimg_frame.duration * project.fps
|
||||||
var content := aimg_frame.content
|
var content := aimg_frame.content
|
||||||
content.convert(Image.FORMAT_RGBA8)
|
content.convert(project.get_image_format())
|
||||||
frame.cels.append(PixelCel.new(content, 1))
|
frame.cels.append(PixelCel.new(content, 1))
|
||||||
project.frames.append(frame)
|
project.frames.append(frame)
|
||||||
|
|
||||||
|
@ -185,8 +191,8 @@ func handle_loading_video(file: String) -> bool:
|
||||||
project_size.x = temp_image.get_width()
|
project_size.x = temp_image.get_width()
|
||||||
if temp_image.get_height() > project_size.y:
|
if temp_image.get_height() > project_size.y:
|
||||||
project_size.y = temp_image.get_height()
|
project_size.y = temp_image.get_height()
|
||||||
DirAccess.remove_absolute(Export.TEMP_PATH)
|
|
||||||
if images_to_import.size() == 0 or project_size == Vector2i.ZERO:
|
if images_to_import.size() == 0 or project_size == Vector2i.ZERO:
|
||||||
|
DirAccess.remove_absolute(Export.TEMP_PATH)
|
||||||
return false # We didn't find any images, return
|
return false # We didn't find any images, return
|
||||||
# If we found images, create a new project out of them
|
# If we found images, create a new project out of them
|
||||||
var new_project := Project.new([], file.get_basename().get_file(), project_size)
|
var new_project := Project.new([], file.get_basename().get_file(), project_size)
|
||||||
|
@ -196,6 +202,14 @@ func handle_loading_video(file: String) -> bool:
|
||||||
Global.projects.append(new_project)
|
Global.projects.append(new_project)
|
||||||
Global.tabs.current_tab = Global.tabs.get_tab_count() - 1
|
Global.tabs.current_tab = Global.tabs.get_tab_count() - 1
|
||||||
Global.canvas.camera_zoom()
|
Global.canvas.camera_zoom()
|
||||||
|
var output_audio_file := temp_path_real.path_join("audio.mp3")
|
||||||
|
# ffmpeg -y -i input_file -vn audio.mp3
|
||||||
|
var ffmpeg_execute_audio: PackedStringArray = ["-y", "-i", file, "-vn", output_audio_file]
|
||||||
|
OS.execute(Global.ffmpeg_path, ffmpeg_execute_audio, [], true)
|
||||||
|
if FileAccess.file_exists(output_audio_file):
|
||||||
|
open_audio_file(output_audio_file)
|
||||||
|
temp_dir.remove("audio.mp3")
|
||||||
|
DirAccess.remove_absolute(Export.TEMP_PATH)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
|
||||||
|
@ -258,6 +272,18 @@ func open_pxo_file(path: String, is_backup := false, replace_empty := true) -> v
|
||||||
new_project.tiles.tile_mask = image
|
new_project.tiles.tile_mask = image
|
||||||
else:
|
else:
|
||||||
new_project.tiles.reset_mask()
|
new_project.tiles.reset_mask()
|
||||||
|
if result.has("tilesets"):
|
||||||
|
for i in result.tilesets.size():
|
||||||
|
var tileset_dict: Dictionary = result.tilesets[i]
|
||||||
|
var tileset := new_project.tilesets[i]
|
||||||
|
var tile_size := tileset.tile_size
|
||||||
|
var tile_amount: int = tileset_dict.tile_amount
|
||||||
|
for j in tile_amount:
|
||||||
|
var image_data := zip_reader.read_file("tilesets/%s/%s" % [i, j])
|
||||||
|
var image := Image.create_from_data(
|
||||||
|
tile_size.x, tile_size.y, false, new_project.get_image_format(), image_data
|
||||||
|
)
|
||||||
|
tileset.add_tile(image, null)
|
||||||
zip_reader.close()
|
zip_reader.close()
|
||||||
new_project.export_directory_path = path.get_base_dir()
|
new_project.export_directory_path = path.get_base_dir()
|
||||||
|
|
||||||
|
@ -389,18 +415,23 @@ func save_pxo_file(
|
||||||
var frame_index := 1
|
var frame_index := 1
|
||||||
for frame in project.frames:
|
for frame in project.frames:
|
||||||
if not autosave and include_blended:
|
if not autosave and include_blended:
|
||||||
var blended := Image.create(project.size.x, project.size.y, false, Image.FORMAT_RGBA8)
|
var blended := project.new_empty_image()
|
||||||
DrawingAlgos.blend_layers(blended, frame, Vector2i.ZERO, project)
|
DrawingAlgos.blend_layers(blended, frame, Vector2i.ZERO, project)
|
||||||
zip_packer.start_file("image_data/final_images/%s" % frame_index)
|
zip_packer.start_file("image_data/final_images/%s" % frame_index)
|
||||||
zip_packer.write_file(blended.get_data())
|
zip_packer.write_file(blended.get_data())
|
||||||
zip_packer.close_file()
|
zip_packer.close_file()
|
||||||
var cel_index := 1
|
var cel_index := 1
|
||||||
for cel in frame.cels:
|
for cel in frame.cels:
|
||||||
var cel_image := cel.get_image()
|
var cel_image := cel.get_image() as ImageExtended
|
||||||
if is_instance_valid(cel_image) and cel is PixelCel:
|
if is_instance_valid(cel_image) and cel is PixelCel:
|
||||||
zip_packer.start_file("image_data/frames/%s/layer_%s" % [frame_index, cel_index])
|
zip_packer.start_file("image_data/frames/%s/layer_%s" % [frame_index, cel_index])
|
||||||
zip_packer.write_file(cel_image.get_data())
|
zip_packer.write_file(cel_image.get_data())
|
||||||
zip_packer.close_file()
|
zip_packer.close_file()
|
||||||
|
zip_packer.start_file(
|
||||||
|
"image_data/frames/%s/indices_layer_%s" % [frame_index, cel_index]
|
||||||
|
)
|
||||||
|
zip_packer.write_file(cel_image.indices_image.get_data())
|
||||||
|
zip_packer.close_file()
|
||||||
cel_index += 1
|
cel_index += 1
|
||||||
frame_index += 1
|
frame_index += 1
|
||||||
var brush_index := 0
|
var brush_index := 0
|
||||||
|
@ -413,6 +444,22 @@ func save_pxo_file(
|
||||||
zip_packer.start_file("image_data/tile_map")
|
zip_packer.start_file("image_data/tile_map")
|
||||||
zip_packer.write_file(project.tiles.tile_mask.get_data())
|
zip_packer.write_file(project.tiles.tile_mask.get_data())
|
||||||
zip_packer.close_file()
|
zip_packer.close_file()
|
||||||
|
for i in project.tilesets.size():
|
||||||
|
var tileset := project.tilesets[i]
|
||||||
|
var tileset_path := "tilesets/%s" % i
|
||||||
|
for j in tileset.tiles.size():
|
||||||
|
var tile := tileset.tiles[j]
|
||||||
|
zip_packer.start_file(tileset_path.path_join(str(j)))
|
||||||
|
zip_packer.write_file(tile.image.get_data())
|
||||||
|
zip_packer.close_file()
|
||||||
|
var audio_layers := project.get_all_audio_layers()
|
||||||
|
for i in audio_layers.size():
|
||||||
|
var layer := audio_layers[i]
|
||||||
|
var audio_path := "audio/%s" % i
|
||||||
|
if layer.audio is AudioStreamMP3:
|
||||||
|
zip_packer.start_file(audio_path)
|
||||||
|
zip_packer.write_file(layer.audio.data)
|
||||||
|
zip_packer.close_file()
|
||||||
zip_packer.close()
|
zip_packer.close()
|
||||||
|
|
||||||
if temp_path != path:
|
if temp_path != path:
|
||||||
|
@ -457,12 +504,13 @@ func save_pxo_file(
|
||||||
|
|
||||||
func open_image_as_new_tab(path: String, image: Image) -> void:
|
func open_image_as_new_tab(path: String, image: Image) -> void:
|
||||||
var project := Project.new([], path.get_file(), image.get_size())
|
var project := Project.new([], path.get_file(), image.get_size())
|
||||||
project.layers.append(PixelLayer.new(project))
|
var layer := PixelLayer.new(project)
|
||||||
|
project.layers.append(layer)
|
||||||
Global.projects.append(project)
|
Global.projects.append(project)
|
||||||
|
|
||||||
var frame := Frame.new()
|
var frame := Frame.new()
|
||||||
image.convert(Image.FORMAT_RGBA8)
|
image.convert(project.get_image_format())
|
||||||
frame.cels.append(PixelCel.new(image, 1))
|
frame.cels.append(layer.new_cel_from_image(image))
|
||||||
|
|
||||||
project.frames.append(frame)
|
project.frames.append(frame)
|
||||||
set_new_imported_tab(project, path)
|
set_new_imported_tab(project, path)
|
||||||
|
@ -475,15 +523,18 @@ func open_image_as_spritesheet_tab_smart(
|
||||||
frame_size = image.get_size()
|
frame_size = image.get_size()
|
||||||
sliced_rects.append(Rect2i(Vector2i.ZERO, frame_size))
|
sliced_rects.append(Rect2i(Vector2i.ZERO, frame_size))
|
||||||
var project := Project.new([], path.get_file(), frame_size)
|
var project := Project.new([], path.get_file(), frame_size)
|
||||||
project.layers.append(PixelLayer.new(project))
|
var layer := PixelLayer.new(project)
|
||||||
|
project.layers.append(layer)
|
||||||
Global.projects.append(project)
|
Global.projects.append(project)
|
||||||
for rect in sliced_rects:
|
for rect in sliced_rects:
|
||||||
var offset: Vector2 = (0.5 * (frame_size - rect.size)).floor()
|
var offset: Vector2 = (0.5 * (frame_size - rect.size)).floor()
|
||||||
var frame := Frame.new()
|
var frame := Frame.new()
|
||||||
var cropped_image := Image.create(frame_size.x, frame_size.y, false, Image.FORMAT_RGBA8)
|
var cropped_image := Image.create(
|
||||||
image.convert(Image.FORMAT_RGBA8)
|
frame_size.x, frame_size.y, false, project.get_image_format()
|
||||||
|
)
|
||||||
|
image.convert(project.get_image_format())
|
||||||
cropped_image.blit_rect(image, rect, offset)
|
cropped_image.blit_rect(image, rect, offset)
|
||||||
frame.cels.append(PixelCel.new(cropped_image, 1))
|
frame.cels.append(layer.new_cel_from_image(cropped_image))
|
||||||
project.frames.append(frame)
|
project.frames.append(frame)
|
||||||
set_new_imported_tab(project, path)
|
set_new_imported_tab(project, path)
|
||||||
|
|
||||||
|
@ -494,7 +545,8 @@ func open_image_as_spritesheet_tab(path: String, image: Image, horiz: int, vert:
|
||||||
var frame_width := image.get_size().x / horiz
|
var frame_width := image.get_size().x / horiz
|
||||||
var frame_height := image.get_size().y / vert
|
var frame_height := image.get_size().y / vert
|
||||||
var project := Project.new([], path.get_file(), Vector2(frame_width, frame_height))
|
var project := Project.new([], path.get_file(), Vector2(frame_width, frame_height))
|
||||||
project.layers.append(PixelLayer.new(project))
|
var layer := PixelLayer.new(project)
|
||||||
|
project.layers.append(layer)
|
||||||
Global.projects.append(project)
|
Global.projects.append(project)
|
||||||
for yy in range(vert):
|
for yy in range(vert):
|
||||||
for xx in range(horiz):
|
for xx in range(horiz):
|
||||||
|
@ -503,8 +555,8 @@ func open_image_as_spritesheet_tab(path: String, image: Image, horiz: int, vert:
|
||||||
Rect2i(frame_width * xx, frame_height * yy, frame_width, frame_height)
|
Rect2i(frame_width * xx, frame_height * yy, frame_width, frame_height)
|
||||||
)
|
)
|
||||||
project.size = cropped_image.get_size()
|
project.size = cropped_image.get_size()
|
||||||
cropped_image.convert(Image.FORMAT_RGBA8)
|
cropped_image.convert(project.get_image_format())
|
||||||
frame.cels.append(PixelCel.new(cropped_image, 1))
|
frame.cels.append(layer.new_cel_from_image(cropped_image))
|
||||||
project.frames.append(frame)
|
project.frames.append(frame)
|
||||||
set_new_imported_tab(project, path)
|
set_new_imported_tab(project, path)
|
||||||
|
|
||||||
|
@ -562,12 +614,12 @@ func open_image_as_spritesheet_layer_smart(
|
||||||
if f >= start_frame and f < (start_frame + sliced_rects.size()):
|
if f >= start_frame and f < (start_frame + sliced_rects.size()):
|
||||||
# Slice spritesheet
|
# Slice spritesheet
|
||||||
var offset: Vector2 = (0.5 * (frame_size - sliced_rects[f - start_frame].size)).floor()
|
var offset: Vector2 = (0.5 * (frame_size - sliced_rects[f - start_frame].size)).floor()
|
||||||
image.convert(Image.FORMAT_RGBA8)
|
image.convert(project.get_image_format())
|
||||||
var cropped_image := Image.create(
|
var cropped_image := Image.create(
|
||||||
project_width, project_height, false, Image.FORMAT_RGBA8
|
project_width, project_height, false, project.get_image_format()
|
||||||
)
|
)
|
||||||
cropped_image.blit_rect(image, sliced_rects[f - start_frame], offset)
|
cropped_image.blit_rect(image, sliced_rects[f - start_frame], offset)
|
||||||
cels.append(PixelCel.new(cropped_image))
|
cels.append(layer.new_cel_from_image(cropped_image))
|
||||||
else:
|
else:
|
||||||
cels.append(layer.new_empty_cel())
|
cels.append(layer.new_empty_cel())
|
||||||
|
|
||||||
|
@ -644,16 +696,16 @@ func open_image_as_spritesheet_layer(
|
||||||
# Slice spritesheet
|
# Slice spritesheet
|
||||||
var xx := (f - start_frame) % horizontal
|
var xx := (f - start_frame) % horizontal
|
||||||
var yy := (f - start_frame) / horizontal
|
var yy := (f - start_frame) / horizontal
|
||||||
image.convert(Image.FORMAT_RGBA8)
|
image.convert(project.get_image_format())
|
||||||
var cropped_image := Image.create(
|
var cropped_image := Image.create(
|
||||||
project_width, project_height, false, Image.FORMAT_RGBA8
|
project_width, project_height, false, project.get_image_format()
|
||||||
)
|
)
|
||||||
cropped_image.blit_rect(
|
cropped_image.blit_rect(
|
||||||
image,
|
image,
|
||||||
Rect2i(frame_width * xx, frame_height * yy, frame_width, frame_height),
|
Rect2i(frame_width * xx, frame_height * yy, frame_width, frame_height),
|
||||||
Vector2i.ZERO
|
Vector2i.ZERO
|
||||||
)
|
)
|
||||||
cels.append(PixelCel.new(cropped_image))
|
cels.append(layer.new_cel_from_image(cropped_image))
|
||||||
else:
|
else:
|
||||||
cels.append(layer.new_empty_cel())
|
cels.append(layer.new_empty_cel())
|
||||||
|
|
||||||
|
@ -687,13 +739,20 @@ func open_image_at_cel(image: Image, layer_index := 0, frame_index := 0) -> void
|
||||||
var cel := project.frames[frame_index].cels[layer_index]
|
var cel := project.frames[frame_index].cels[layer_index]
|
||||||
if not cel is PixelCel:
|
if not cel is PixelCel:
|
||||||
return
|
return
|
||||||
image.convert(Image.FORMAT_RGBA8)
|
image.convert(project.get_image_format())
|
||||||
var cel_image := Image.create(project_width, project_height, false, Image.FORMAT_RGBA8)
|
var cel_image := (cel as PixelCel).get_image()
|
||||||
|
var undo_data := {}
|
||||||
|
if cel is CelTileMap:
|
||||||
|
undo_data[cel] = (cel as CelTileMap).serialize_undo_data()
|
||||||
|
cel_image.add_data_to_dictionary(undo_data)
|
||||||
cel_image.blit_rect(image, Rect2i(Vector2i.ZERO, image.get_size()), Vector2i.ZERO)
|
cel_image.blit_rect(image, Rect2i(Vector2i.ZERO, image.get_size()), Vector2i.ZERO)
|
||||||
Global.undo_redo_compress_images(
|
cel_image.convert_rgb_to_indexed()
|
||||||
{cel.image: cel_image.data}, {cel.image: cel.image.data}, project
|
var redo_data := {}
|
||||||
)
|
if cel is CelTileMap:
|
||||||
|
(cel as CelTileMap).update_tilemap()
|
||||||
|
redo_data[cel] = (cel as CelTileMap).serialize_undo_data()
|
||||||
|
cel_image.add_data_to_dictionary(redo_data)
|
||||||
|
project.deserialize_cel_undo_data(redo_data, undo_data)
|
||||||
project.undo_redo.add_do_property(project, "selected_cels", [])
|
project.undo_redo.add_do_property(project, "selected_cels", [])
|
||||||
project.undo_redo.add_do_method(project.change_cel.bind(frame_index, layer_index))
|
project.undo_redo.add_do_method(project.change_cel.bind(frame_index, layer_index))
|
||||||
project.undo_redo.add_do_method(Global.undo_or_redo.bind(false))
|
project.undo_redo.add_do_method(Global.undo_or_redo.bind(false))
|
||||||
|
@ -716,11 +775,14 @@ func open_image_as_new_frame(
|
||||||
|
|
||||||
var frame := Frame.new()
|
var frame := Frame.new()
|
||||||
for i in project.layers.size():
|
for i in project.layers.size():
|
||||||
if i == layer_index:
|
var layer := project.layers[i]
|
||||||
image.convert(Image.FORMAT_RGBA8)
|
if i == layer_index and layer is PixelLayer:
|
||||||
var cel_image := Image.create(project_width, project_height, false, Image.FORMAT_RGBA8)
|
image.convert(project.get_image_format())
|
||||||
|
var cel_image := Image.create(
|
||||||
|
project_width, project_height, false, project.get_image_format()
|
||||||
|
)
|
||||||
cel_image.blit_rect(image, Rect2i(Vector2i.ZERO, image.get_size()), Vector2i.ZERO)
|
cel_image.blit_rect(image, Rect2i(Vector2i.ZERO, image.get_size()), Vector2i.ZERO)
|
||||||
frame.cels.append(PixelCel.new(cel_image, 1))
|
frame.cels.append(layer.new_cel_from_image(cel_image))
|
||||||
else:
|
else:
|
||||||
frame.cels.append(project.layers[i].new_empty_cel())
|
frame.cels.append(project.layers[i].new_empty_cel())
|
||||||
if not undo:
|
if not undo:
|
||||||
|
@ -753,10 +815,12 @@ func open_image_as_new_layer(image: Image, file_name: String, frame_index := 0)
|
||||||
Global.current_project.undo_redo.create_action("Add Layer")
|
Global.current_project.undo_redo.create_action("Add Layer")
|
||||||
for i in project.frames.size():
|
for i in project.frames.size():
|
||||||
if i == frame_index:
|
if i == frame_index:
|
||||||
image.convert(Image.FORMAT_RGBA8)
|
image.convert(project.get_image_format())
|
||||||
var cel_image := Image.create(project_width, project_height, false, Image.FORMAT_RGBA8)
|
var cel_image := Image.create(
|
||||||
|
project_width, project_height, false, project.get_image_format()
|
||||||
|
)
|
||||||
cel_image.blit_rect(image, Rect2i(Vector2i.ZERO, image.get_size()), Vector2i.ZERO)
|
cel_image.blit_rect(image, Rect2i(Vector2i.ZERO, image.get_size()), Vector2i.ZERO)
|
||||||
cels.append(PixelCel.new(cel_image, 1))
|
cels.append(layer.new_cel_from_image(cel_image))
|
||||||
else:
|
else:
|
||||||
cels.append(layer.new_empty_cel())
|
cels.append(layer.new_empty_cel())
|
||||||
|
|
||||||
|
@ -794,6 +858,49 @@ func import_reference_image_from_image(image: Image) -> void:
|
||||||
reference_image_imported.emit()
|
reference_image_imported.emit()
|
||||||
|
|
||||||
|
|
||||||
|
func open_image_as_tileset(
|
||||||
|
path: String, image: Image, horiz: int, vert: int, project := Global.current_project
|
||||||
|
) -> void:
|
||||||
|
image.convert(project.get_image_format())
|
||||||
|
horiz = mini(horiz, image.get_size().x)
|
||||||
|
vert = mini(vert, image.get_size().y)
|
||||||
|
var frame_width := image.get_size().x / horiz
|
||||||
|
var frame_height := image.get_size().y / vert
|
||||||
|
var tile_size := Vector2i(frame_width, frame_height)
|
||||||
|
var tileset := TileSetCustom.new(tile_size, path.get_basename().get_file())
|
||||||
|
for yy in range(vert):
|
||||||
|
for xx in range(horiz):
|
||||||
|
var cropped_image := image.get_region(
|
||||||
|
Rect2i(frame_width * xx, frame_height * yy, frame_width, frame_height)
|
||||||
|
)
|
||||||
|
@warning_ignore("int_as_enum_without_cast")
|
||||||
|
tileset.add_tile(cropped_image, null)
|
||||||
|
project.tilesets.append(tileset)
|
||||||
|
|
||||||
|
|
||||||
|
func open_image_as_tileset_smart(
|
||||||
|
path: String,
|
||||||
|
image: Image,
|
||||||
|
sliced_rects: Array[Rect2i],
|
||||||
|
tile_size: Vector2i,
|
||||||
|
project := Global.current_project
|
||||||
|
) -> void:
|
||||||
|
image.convert(project.get_image_format())
|
||||||
|
if sliced_rects.size() == 0: # Image is empty sprite (manually set data to be consistent)
|
||||||
|
tile_size = image.get_size()
|
||||||
|
sliced_rects.append(Rect2i(Vector2i.ZERO, tile_size))
|
||||||
|
var tileset := TileSetCustom.new(tile_size, path.get_basename().get_file())
|
||||||
|
for rect in sliced_rects:
|
||||||
|
var offset: Vector2 = (0.5 * (tile_size - rect.size)).floor()
|
||||||
|
var cropped_image := Image.create(
|
||||||
|
tile_size.x, tile_size.y, false, project.get_image_format()
|
||||||
|
)
|
||||||
|
cropped_image.blit_rect(image, rect, offset)
|
||||||
|
@warning_ignore("int_as_enum_without_cast")
|
||||||
|
tileset.add_tile(cropped_image, null)
|
||||||
|
project.tilesets.append(tileset)
|
||||||
|
|
||||||
|
|
||||||
func set_new_imported_tab(project: Project, path: String) -> void:
|
func set_new_imported_tab(project: Project, path: String) -> void:
|
||||||
var prev_project_empty := Global.current_project.is_empty()
|
var prev_project_empty := Global.current_project.is_empty()
|
||||||
var prev_project_pos := Global.current_project_index
|
var prev_project_pos := Global.current_project_index
|
||||||
|
@ -817,6 +924,23 @@ func set_new_imported_tab(project: Project, path: String) -> void:
|
||||||
Global.tabs.delete_tab(prev_project_pos)
|
Global.tabs.delete_tab(prev_project_pos)
|
||||||
|
|
||||||
|
|
||||||
|
func open_audio_file(path: String) -> void:
|
||||||
|
var audio_stream: AudioStream
|
||||||
|
var file := FileAccess.open(path, FileAccess.READ)
|
||||||
|
audio_stream = AudioStreamMP3.new()
|
||||||
|
audio_stream.data = file.get_buffer(file.get_length())
|
||||||
|
if not is_instance_valid(audio_stream):
|
||||||
|
return
|
||||||
|
var project := Global.current_project
|
||||||
|
for layer in project.layers:
|
||||||
|
if layer is AudioLayer and not is_instance_valid(layer.audio):
|
||||||
|
layer.audio = audio_stream
|
||||||
|
return
|
||||||
|
var new_layer := AudioLayer.new(project, path.get_basename().get_file())
|
||||||
|
new_layer.audio = audio_stream
|
||||||
|
Global.animation_timeline.add_layer(new_layer, project)
|
||||||
|
|
||||||
|
|
||||||
func update_autosave() -> void:
|
func update_autosave() -> void:
|
||||||
if not is_instance_valid(autosave_timer):
|
if not is_instance_valid(autosave_timer):
|
||||||
return
|
return
|
||||||
|
|
|
@ -36,9 +36,10 @@ func does_palette_exist(palette_name: String) -> bool:
|
||||||
|
|
||||||
|
|
||||||
func select_palette(palette_name: String) -> void:
|
func select_palette(palette_name: String) -> void:
|
||||||
current_palette = palettes.get(palette_name)
|
current_palette = palettes.get(palette_name, null)
|
||||||
_clear_selected_colors()
|
_clear_selected_colors()
|
||||||
Global.config_cache.set_value("data", "last_palette", current_palette.name)
|
if is_instance_valid(current_palette):
|
||||||
|
Global.config_cache.set_value("data", "last_palette", current_palette.name)
|
||||||
palette_selected.emit(palette_name)
|
palette_selected.emit(palette_name)
|
||||||
|
|
||||||
|
|
||||||
|
@ -224,6 +225,7 @@ func current_palete_delete(permanent := true) -> void:
|
||||||
select_palette(palettes.keys()[0])
|
select_palette(palettes.keys()[0])
|
||||||
else:
|
else:
|
||||||
current_palette = null
|
current_palette = null
|
||||||
|
select_palette("")
|
||||||
|
|
||||||
|
|
||||||
func current_palette_add_color(mouse_button: int, start_index := 0) -> void:
|
func current_palette_add_color(mouse_button: int, start_index := 0) -> void:
|
||||||
|
@ -294,13 +296,13 @@ func current_palette_select_color(mouse_button: int, index: int) -> void:
|
||||||
if color == null:
|
if color == null:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
_select_color(mouse_button, index)
|
||||||
|
|
||||||
match mouse_button:
|
match mouse_button:
|
||||||
MOUSE_BUTTON_LEFT:
|
MOUSE_BUTTON_LEFT:
|
||||||
Tools.assign_color(color, mouse_button)
|
Tools.assign_color(color, mouse_button, true, left_selected_color)
|
||||||
MOUSE_BUTTON_RIGHT:
|
MOUSE_BUTTON_RIGHT:
|
||||||
Tools.assign_color(color, mouse_button)
|
Tools.assign_color(color, mouse_button, true, right_selected_color)
|
||||||
|
|
||||||
_select_color(mouse_button, index)
|
|
||||||
|
|
||||||
|
|
||||||
func _select_color(mouse_button: int, index: int) -> void:
|
func _select_color(mouse_button: int, index: int) -> void:
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
# gdlint: ignore=max-public-methods
|
# gdlint: ignore=max-public-methods
|
||||||
extends Node
|
extends Node
|
||||||
|
|
||||||
signal color_changed(color: Color, button: int)
|
signal color_changed(color_info: Dictionary, button: int)
|
||||||
|
@warning_ignore("unused_signal")
|
||||||
|
signal selected_tile_index_changed(tile_index: int)
|
||||||
signal config_changed(slot_idx: int, config: Dictionary)
|
signal config_changed(slot_idx: int, config: Dictionary)
|
||||||
@warning_ignore("unused_signal")
|
@warning_ignore("unused_signal")
|
||||||
signal flip_rotated(flip_x, flip_y, rotate_90, rotate_180, rotate_270)
|
signal flip_rotated(flip_x, flip_y, rotate_90, rotate_180, rotate_270)
|
||||||
|
@ -9,9 +11,15 @@ signal options_reset
|
||||||
|
|
||||||
enum Dynamics { NONE, PRESSURE, VELOCITY }
|
enum Dynamics { NONE, PRESSURE, VELOCITY }
|
||||||
|
|
||||||
|
const XY_LINE := Vector2(-0.707107, 0.707107)
|
||||||
|
const X_MINUS_Y_LINE := Vector2(0.707107, 0.707107)
|
||||||
|
|
||||||
|
var active_button := -1
|
||||||
var picking_color_for := MOUSE_BUTTON_LEFT
|
var picking_color_for := MOUSE_BUTTON_LEFT
|
||||||
var horizontal_mirror := false
|
var horizontal_mirror := false
|
||||||
var vertical_mirror := false
|
var vertical_mirror := false
|
||||||
|
var diagonal_xy_mirror := false
|
||||||
|
var diagonal_x_minus_y_mirror := false
|
||||||
var pixel_perfect := false
|
var pixel_perfect := false
|
||||||
var alpha_locked := false
|
var alpha_locked := false
|
||||||
|
|
||||||
|
@ -82,7 +90,11 @@ var tools := {
|
||||||
),
|
),
|
||||||
"Move":
|
"Move":
|
||||||
Tool.new(
|
Tool.new(
|
||||||
"Move", "Move", "move", "res://src/Tools/UtilityTools/Move.tscn", [Global.LayerTypes.PIXEL]
|
"Move",
|
||||||
|
"Move",
|
||||||
|
"move",
|
||||||
|
"res://src/Tools/UtilityTools/Move.tscn",
|
||||||
|
[Global.LayerTypes.PIXEL, Global.LayerTypes.TILEMAP]
|
||||||
),
|
),
|
||||||
"Zoom": Tool.new("Zoom", "Zoom", "zoom", "res://src/Tools/UtilityTools/Zoom.tscn"),
|
"Zoom": Tool.new("Zoom", "Zoom", "zoom", "res://src/Tools/UtilityTools/Zoom.tscn"),
|
||||||
"Pan": Tool.new("Pan", "Pan", "pan", "res://src/Tools/UtilityTools/Pan.tscn"),
|
"Pan": Tool.new("Pan", "Pan", "pan", "res://src/Tools/UtilityTools/Pan.tscn"),
|
||||||
|
@ -110,7 +122,7 @@ var tools := {
|
||||||
"Pencil",
|
"Pencil",
|
||||||
"pencil",
|
"pencil",
|
||||||
"res://src/Tools/DesignTools/Pencil.tscn",
|
"res://src/Tools/DesignTools/Pencil.tscn",
|
||||||
[Global.LayerTypes.PIXEL],
|
[Global.LayerTypes.PIXEL, Global.LayerTypes.TILEMAP],
|
||||||
"Hold %s to make a line",
|
"Hold %s to make a line",
|
||||||
["draw_create_line"]
|
["draw_create_line"]
|
||||||
),
|
),
|
||||||
|
@ -120,7 +132,7 @@ var tools := {
|
||||||
"Eraser",
|
"Eraser",
|
||||||
"eraser",
|
"eraser",
|
||||||
"res://src/Tools/DesignTools/Eraser.tscn",
|
"res://src/Tools/DesignTools/Eraser.tscn",
|
||||||
[Global.LayerTypes.PIXEL],
|
[Global.LayerTypes.PIXEL, Global.LayerTypes.TILEMAP],
|
||||||
"Hold %s to make a line",
|
"Hold %s to make a line",
|
||||||
["draw_create_line"]
|
["draw_create_line"]
|
||||||
),
|
),
|
||||||
|
@ -130,7 +142,7 @@ var tools := {
|
||||||
"Bucket",
|
"Bucket",
|
||||||
"fill",
|
"fill",
|
||||||
"res://src/Tools/DesignTools/Bucket.tscn",
|
"res://src/Tools/DesignTools/Bucket.tscn",
|
||||||
[Global.LayerTypes.PIXEL]
|
[Global.LayerTypes.PIXEL, Global.LayerTypes.TILEMAP]
|
||||||
),
|
),
|
||||||
"Shading":
|
"Shading":
|
||||||
Tool.new(
|
Tool.new(
|
||||||
|
@ -138,7 +150,7 @@ var tools := {
|
||||||
"Shading Tool",
|
"Shading Tool",
|
||||||
"shading",
|
"shading",
|
||||||
"res://src/Tools/DesignTools/Shading.tscn",
|
"res://src/Tools/DesignTools/Shading.tscn",
|
||||||
[Global.LayerTypes.PIXEL]
|
[Global.LayerTypes.PIXEL, Global.LayerTypes.TILEMAP]
|
||||||
),
|
),
|
||||||
"LineTool":
|
"LineTool":
|
||||||
(
|
(
|
||||||
|
@ -148,7 +160,7 @@ var tools := {
|
||||||
"Line Tool",
|
"Line Tool",
|
||||||
"linetool",
|
"linetool",
|
||||||
"res://src/Tools/DesignTools/LineTool.tscn",
|
"res://src/Tools/DesignTools/LineTool.tscn",
|
||||||
[Global.LayerTypes.PIXEL],
|
[Global.LayerTypes.PIXEL, Global.LayerTypes.TILEMAP],
|
||||||
"""Hold %s to snap the angle of the line
|
"""Hold %s to snap the angle of the line
|
||||||
Hold %s to center the shape on the click origin
|
Hold %s to center the shape on the click origin
|
||||||
Hold %s to displace the shape's origin""",
|
Hold %s to displace the shape's origin""",
|
||||||
|
@ -163,7 +175,7 @@ Hold %s to displace the shape's origin""",
|
||||||
"Curve Tool",
|
"Curve Tool",
|
||||||
"curvetool",
|
"curvetool",
|
||||||
"res://src/Tools/DesignTools/CurveTool.tscn",
|
"res://src/Tools/DesignTools/CurveTool.tscn",
|
||||||
[Global.LayerTypes.PIXEL],
|
[Global.LayerTypes.PIXEL, Global.LayerTypes.TILEMAP],
|
||||||
"""Draws bezier curves
|
"""Draws bezier curves
|
||||||
Press %s/%s to add new points
|
Press %s/%s to add new points
|
||||||
Press and drag to control the curvature
|
Press and drag to control the curvature
|
||||||
|
@ -179,7 +191,7 @@ Press %s to remove the last added point""",
|
||||||
"Rectangle Tool",
|
"Rectangle Tool",
|
||||||
"rectangletool",
|
"rectangletool",
|
||||||
"res://src/Tools/DesignTools/RectangleTool.tscn",
|
"res://src/Tools/DesignTools/RectangleTool.tscn",
|
||||||
[Global.LayerTypes.PIXEL],
|
[Global.LayerTypes.PIXEL, Global.LayerTypes.TILEMAP],
|
||||||
"""Hold %s to create a 1:1 shape
|
"""Hold %s to create a 1:1 shape
|
||||||
Hold %s to center the shape on the click origin
|
Hold %s to center the shape on the click origin
|
||||||
Hold %s to displace the shape's origin""",
|
Hold %s to displace the shape's origin""",
|
||||||
|
@ -194,7 +206,7 @@ Hold %s to displace the shape's origin""",
|
||||||
"Ellipse Tool",
|
"Ellipse Tool",
|
||||||
"ellipsetool",
|
"ellipsetool",
|
||||||
"res://src/Tools/DesignTools/EllipseTool.tscn",
|
"res://src/Tools/DesignTools/EllipseTool.tscn",
|
||||||
[Global.LayerTypes.PIXEL],
|
[Global.LayerTypes.PIXEL, Global.LayerTypes.TILEMAP],
|
||||||
"""Hold %s to create a 1:1 shape
|
"""Hold %s to create a 1:1 shape
|
||||||
Hold %s to center the shape on the click origin
|
Hold %s to center the shape on the click origin
|
||||||
Hold %s to displace the shape's origin""",
|
Hold %s to displace the shape's origin""",
|
||||||
|
@ -207,7 +219,7 @@ Hold %s to displace the shape's origin""",
|
||||||
"Text",
|
"Text",
|
||||||
"text",
|
"text",
|
||||||
"res://src/Tools/UtilityTools/Text.tscn",
|
"res://src/Tools/UtilityTools/Text.tscn",
|
||||||
[Global.LayerTypes.PIXEL],
|
[Global.LayerTypes.PIXEL, Global.LayerTypes.TILEMAP],
|
||||||
""
|
""
|
||||||
),
|
),
|
||||||
"3DShapeEdit":
|
"3DShapeEdit":
|
||||||
|
@ -226,14 +238,15 @@ var _panels := {}
|
||||||
var _curr_layer_type := Global.LayerTypes.PIXEL
|
var _curr_layer_type := Global.LayerTypes.PIXEL
|
||||||
var _left_tools_per_layer_type := {
|
var _left_tools_per_layer_type := {
|
||||||
Global.LayerTypes.PIXEL: "Pencil",
|
Global.LayerTypes.PIXEL: "Pencil",
|
||||||
|
Global.LayerTypes.TILEMAP: "Pencil",
|
||||||
Global.LayerTypes.THREE_D: "3DShapeEdit",
|
Global.LayerTypes.THREE_D: "3DShapeEdit",
|
||||||
}
|
}
|
||||||
var _right_tools_per_layer_type := {
|
var _right_tools_per_layer_type := {
|
||||||
Global.LayerTypes.PIXEL: "Eraser",
|
Global.LayerTypes.PIXEL: "Eraser",
|
||||||
|
Global.LayerTypes.TILEMAP: "Eraser",
|
||||||
Global.LayerTypes.THREE_D: "Pan",
|
Global.LayerTypes.THREE_D: "Pan",
|
||||||
}
|
}
|
||||||
var _tool_buttons: Node
|
var _tool_buttons: Node
|
||||||
var _active_button := -1
|
|
||||||
var _last_position := Vector2i(Vector2.INF)
|
var _last_position := Vector2i(Vector2.INF)
|
||||||
|
|
||||||
|
|
||||||
|
@ -504,7 +517,7 @@ func swap_color() -> void:
|
||||||
assign_color(left, MOUSE_BUTTON_RIGHT, false)
|
assign_color(left, MOUSE_BUTTON_RIGHT, false)
|
||||||
|
|
||||||
|
|
||||||
func assign_color(color: Color, button: int, change_alpha := true) -> void:
|
func assign_color(color: Color, button: int, change_alpha := true, index: int = -1) -> void:
|
||||||
var c: Color = _slots[button].color
|
var c: Color = _slots[button].color
|
||||||
# This was requested by Issue #54 on GitHub
|
# This was requested by Issue #54 on GitHub
|
||||||
if color.a == 0 and change_alpha:
|
if color.a == 0 and change_alpha:
|
||||||
|
@ -512,7 +525,8 @@ func assign_color(color: Color, button: int, change_alpha := true) -> void:
|
||||||
color.a = 1
|
color.a = 1
|
||||||
_slots[button].color = color
|
_slots[button].color = color
|
||||||
Global.config_cache.set_value(_slots[button].kname, "color", color)
|
Global.config_cache.set_value(_slots[button].kname, "color", color)
|
||||||
color_changed.emit(color, button)
|
var color_info := {"color": color, "index": index}
|
||||||
|
color_changed.emit(color_info, button)
|
||||||
|
|
||||||
|
|
||||||
func get_assigned_color(button: int) -> Color:
|
func get_assigned_color(button: int) -> Color:
|
||||||
|
@ -524,20 +538,132 @@ func get_mirrored_positions(
|
||||||
) -> Array[Vector2i]:
|
) -> Array[Vector2i]:
|
||||||
var positions: Array[Vector2i] = []
|
var positions: Array[Vector2i] = []
|
||||||
if horizontal_mirror:
|
if horizontal_mirror:
|
||||||
var mirror_x := pos
|
var mirror_x := calculate_mirror_horizontal(pos, project, offset)
|
||||||
mirror_x.x = project.x_symmetry_point - pos.x + offset
|
|
||||||
positions.append(mirror_x)
|
positions.append(mirror_x)
|
||||||
if vertical_mirror:
|
if vertical_mirror:
|
||||||
var mirror_xy := mirror_x
|
positions.append(calculate_mirror_vertical(mirror_x, project, offset))
|
||||||
mirror_xy.y = project.y_symmetry_point - pos.y + offset
|
else:
|
||||||
positions.append(mirror_xy)
|
if diagonal_xy_mirror:
|
||||||
|
positions.append(calculate_mirror_xy(mirror_x, project))
|
||||||
|
if diagonal_x_minus_y_mirror:
|
||||||
|
positions.append(calculate_mirror_x_minus_y(mirror_x, project))
|
||||||
if vertical_mirror:
|
if vertical_mirror:
|
||||||
var mirror_y := pos
|
var mirror_y := calculate_mirror_vertical(pos, project, offset)
|
||||||
mirror_y.y = project.y_symmetry_point - pos.y + offset
|
|
||||||
positions.append(mirror_y)
|
positions.append(mirror_y)
|
||||||
|
if diagonal_xy_mirror:
|
||||||
|
positions.append(calculate_mirror_xy(mirror_y, project))
|
||||||
|
if diagonal_x_minus_y_mirror:
|
||||||
|
positions.append(calculate_mirror_x_minus_y(mirror_y, project))
|
||||||
|
if diagonal_xy_mirror:
|
||||||
|
var mirror_diagonal := calculate_mirror_xy(pos, project)
|
||||||
|
positions.append(mirror_diagonal)
|
||||||
|
if not horizontal_mirror and not vertical_mirror and diagonal_x_minus_y_mirror:
|
||||||
|
positions.append(calculate_mirror_x_minus_y(mirror_diagonal, project))
|
||||||
|
if diagonal_x_minus_y_mirror:
|
||||||
|
positions.append(calculate_mirror_x_minus_y(pos, project))
|
||||||
return positions
|
return positions
|
||||||
|
|
||||||
|
|
||||||
|
func calculate_mirror_horizontal(pos: Vector2i, project: Project, offset := 0) -> Vector2i:
|
||||||
|
return Vector2i(project.x_symmetry_point - pos.x + offset, pos.y)
|
||||||
|
|
||||||
|
|
||||||
|
func calculate_mirror_vertical(pos: Vector2i, project: Project, offset := 0) -> Vector2i:
|
||||||
|
return Vector2i(pos.x, project.y_symmetry_point - pos.y + offset)
|
||||||
|
|
||||||
|
|
||||||
|
func calculate_mirror_xy(pos: Vector2i, project: Project) -> Vector2i:
|
||||||
|
return Vector2i(Vector2(pos).reflect(XY_LINE).round()) + Vector2i(project.xy_symmetry_point)
|
||||||
|
|
||||||
|
|
||||||
|
func calculate_mirror_x_minus_y(pos: Vector2i, project: Project) -> Vector2i:
|
||||||
|
return (
|
||||||
|
Vector2i(Vector2(pos).reflect(X_MINUS_Y_LINE).round())
|
||||||
|
+ Vector2i(project.x_minus_y_symmetry_point)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func is_placing_tiles() -> bool:
|
||||||
|
if Global.current_project.frames.size() == 0 or Global.current_project.layers.size() == 0:
|
||||||
|
return false
|
||||||
|
return Global.current_project.get_current_cel() is CelTileMap and TileSetPanel.placing_tiles
|
||||||
|
|
||||||
|
|
||||||
|
func _get_closest_point_to_grid(pos: Vector2, distance: float, grid_pos: Vector2) -> Vector2:
|
||||||
|
# If the cursor is close to the start/origin of a grid cell, snap to that
|
||||||
|
var snap_distance := distance * Vector2.ONE
|
||||||
|
var closest_point := Vector2.INF
|
||||||
|
var rect := Rect2()
|
||||||
|
rect.position = pos - (snap_distance / 4.0)
|
||||||
|
rect.end = pos + (snap_distance / 4.0)
|
||||||
|
if rect.has_point(grid_pos):
|
||||||
|
closest_point = grid_pos
|
||||||
|
return closest_point
|
||||||
|
# If the cursor is far from the grid cell origin but still close to a grid line
|
||||||
|
# Look for a point close to a horizontal grid line
|
||||||
|
var grid_start_hor := Vector2(0, grid_pos.y)
|
||||||
|
var grid_end_hor := Vector2(Global.current_project.size.x, grid_pos.y)
|
||||||
|
var closest_point_hor := get_closest_point_to_segment(
|
||||||
|
pos, distance, grid_start_hor, grid_end_hor
|
||||||
|
)
|
||||||
|
# Look for a point close to a vertical grid line
|
||||||
|
var grid_start_ver := Vector2(grid_pos.x, 0)
|
||||||
|
var grid_end_ver := Vector2(grid_pos.x, Global.current_project.size.y)
|
||||||
|
var closest_point_ver := get_closest_point_to_segment(
|
||||||
|
pos, distance, grid_start_ver, grid_end_ver
|
||||||
|
)
|
||||||
|
# Snap to the closest point to the closest grid line
|
||||||
|
var horizontal_distance := (closest_point_hor - pos).length()
|
||||||
|
var vertical_distance := (closest_point_ver - pos).length()
|
||||||
|
if horizontal_distance < vertical_distance:
|
||||||
|
closest_point = closest_point_hor
|
||||||
|
elif horizontal_distance > vertical_distance:
|
||||||
|
closest_point = closest_point_ver
|
||||||
|
elif horizontal_distance == vertical_distance and closest_point_hor != Vector2.INF:
|
||||||
|
closest_point = grid_pos
|
||||||
|
return closest_point
|
||||||
|
|
||||||
|
|
||||||
|
func get_closest_point_to_segment(
|
||||||
|
pos: Vector2, distance: float, s1: Vector2, s2: Vector2
|
||||||
|
) -> Vector2:
|
||||||
|
var test_line := (s2 - s1).rotated(deg_to_rad(90)).normalized()
|
||||||
|
var from_a := pos - test_line * distance
|
||||||
|
var from_b := pos + test_line * distance
|
||||||
|
var closest_point := Vector2.INF
|
||||||
|
if Geometry2D.segment_intersects_segment(from_a, from_b, s1, s2):
|
||||||
|
closest_point = Geometry2D.get_closest_point_to_segment(pos, s1, s2)
|
||||||
|
return closest_point
|
||||||
|
|
||||||
|
|
||||||
|
func snap_to_rectangular_grid_boundary(
|
||||||
|
pos: Vector2, grid_size: Vector2i, grid_offset := Vector2i.ZERO, snapping_distance := 9999.0
|
||||||
|
) -> Vector2:
|
||||||
|
var grid_pos := pos.snapped(grid_size)
|
||||||
|
grid_pos += Vector2(grid_offset)
|
||||||
|
# keeping grid_pos as is would have been fine but this adds extra accuracy as to
|
||||||
|
# which snap point (from the list below) is closest to mouse and occupy THAT point
|
||||||
|
# t_l is for "top left" and so on
|
||||||
|
var t_l := grid_pos + Vector2(-grid_size.x, -grid_size.y)
|
||||||
|
var t_c := grid_pos + Vector2(0, -grid_size.y)
|
||||||
|
var t_r := grid_pos + Vector2(grid_size.x, -grid_size.y)
|
||||||
|
var m_l := grid_pos + Vector2(-grid_size.x, 0)
|
||||||
|
var m_c := grid_pos
|
||||||
|
var m_r := grid_pos + Vector2(grid_size.x, 0)
|
||||||
|
var b_l := grid_pos + Vector2(-grid_size.x, grid_size.y)
|
||||||
|
var b_c := grid_pos + Vector2(0, grid_size.y)
|
||||||
|
var b_r := grid_pos + Vector2(grid_size)
|
||||||
|
var vec_arr: PackedVector2Array = [t_l, t_c, t_r, m_l, m_c, m_r, b_l, b_c, b_r]
|
||||||
|
for vec in vec_arr:
|
||||||
|
if vec.distance_to(pos) < grid_pos.distance_to(pos):
|
||||||
|
grid_pos = vec
|
||||||
|
|
||||||
|
var grid_point := _get_closest_point_to_grid(pos, snapping_distance, grid_pos)
|
||||||
|
if grid_point != Vector2.INF:
|
||||||
|
pos = grid_point.floor()
|
||||||
|
return pos
|
||||||
|
|
||||||
|
|
||||||
func set_button_size(button_size: int) -> void:
|
func set_button_size(button_size: int) -> void:
|
||||||
var size := Vector2(24, 24) if button_size == Global.ButtonSize.SMALL else Vector2(32, 32)
|
var size := Vector2(24, 24) if button_size == Global.ButtonSize.SMALL else Vector2(32, 32)
|
||||||
if not is_instance_valid(_tool_buttons):
|
if not is_instance_valid(_tool_buttons):
|
||||||
|
@ -591,32 +717,28 @@ func handle_draw(position: Vector2i, event: InputEvent) -> void:
|
||||||
change_layer_automatically(draw_pos)
|
change_layer_automatically(draw_pos)
|
||||||
return
|
return
|
||||||
|
|
||||||
if event.is_action_pressed(&"activate_left_tool") and _active_button == -1 and not pen_inverted:
|
if event.is_action_pressed(&"activate_left_tool") and active_button == -1 and not pen_inverted:
|
||||||
_active_button = MOUSE_BUTTON_LEFT
|
active_button = MOUSE_BUTTON_LEFT
|
||||||
_slots[_active_button].tool_node.draw_start(draw_pos)
|
_slots[active_button].tool_node.draw_start(draw_pos)
|
||||||
elif event.is_action_released(&"activate_left_tool") and _active_button == MOUSE_BUTTON_LEFT:
|
elif event.is_action_released(&"activate_left_tool") and active_button == MOUSE_BUTTON_LEFT:
|
||||||
_slots[_active_button].tool_node.draw_end(draw_pos)
|
_slots[active_button].tool_node.draw_end(draw_pos)
|
||||||
_active_button = -1
|
active_button = -1
|
||||||
elif (
|
elif (
|
||||||
(
|
(
|
||||||
event.is_action_pressed(&"activate_right_tool")
|
event.is_action_pressed(&"activate_right_tool")
|
||||||
and _active_button == -1
|
and active_button == -1
|
||||||
and not pen_inverted
|
and not pen_inverted
|
||||||
)
|
)
|
||||||
or (
|
or event.is_action_pressed(&"activate_left_tool") and active_button == -1 and pen_inverted
|
||||||
event.is_action_pressed(&"activate_left_tool") and _active_button == -1 and pen_inverted
|
|
||||||
)
|
|
||||||
):
|
):
|
||||||
_active_button = MOUSE_BUTTON_RIGHT
|
active_button = MOUSE_BUTTON_RIGHT
|
||||||
_slots[_active_button].tool_node.draw_start(draw_pos)
|
_slots[active_button].tool_node.draw_start(draw_pos)
|
||||||
elif (
|
elif (
|
||||||
(event.is_action_released(&"activate_right_tool") and _active_button == MOUSE_BUTTON_RIGHT)
|
(event.is_action_released(&"activate_right_tool") and active_button == MOUSE_BUTTON_RIGHT)
|
||||||
or (
|
or event.is_action_released(&"activate_left_tool") and active_button == MOUSE_BUTTON_RIGHT
|
||||||
event.is_action_released(&"activate_left_tool") and _active_button == MOUSE_BUTTON_RIGHT
|
|
||||||
)
|
|
||||||
):
|
):
|
||||||
_slots[_active_button].tool_node.draw_end(draw_pos)
|
_slots[active_button].tool_node.draw_end(draw_pos)
|
||||||
_active_button = -1
|
active_button = -1
|
||||||
|
|
||||||
if event is InputEventMouseMotion:
|
if event is InputEventMouseMotion:
|
||||||
pen_pressure = event.pressure
|
pen_pressure = event.pressure
|
||||||
|
@ -647,8 +769,8 @@ func handle_draw(position: Vector2i, event: InputEvent) -> void:
|
||||||
_last_position = position
|
_last_position = position
|
||||||
_slots[MOUSE_BUTTON_LEFT].tool_node.cursor_move(position)
|
_slots[MOUSE_BUTTON_LEFT].tool_node.cursor_move(position)
|
||||||
_slots[MOUSE_BUTTON_RIGHT].tool_node.cursor_move(position)
|
_slots[MOUSE_BUTTON_RIGHT].tool_node.cursor_move(position)
|
||||||
if _active_button != -1:
|
if active_button != -1:
|
||||||
_slots[_active_button].tool_node.draw_move(draw_pos)
|
_slots[active_button].tool_node.draw_move(draw_pos)
|
||||||
|
|
||||||
var project := Global.current_project
|
var project := Global.current_project
|
||||||
var text := "[%s×%s]" % [project.size.x, project.size.y]
|
var text := "[%s×%s]" % [project.size.x, project.size.y]
|
||||||
|
@ -678,7 +800,10 @@ func _cel_switched() -> void:
|
||||||
var layer: BaseLayer = Global.current_project.layers[Global.current_project.current_layer]
|
var layer: BaseLayer = Global.current_project.layers[Global.current_project.current_layer]
|
||||||
var layer_type := layer.get_layer_type()
|
var layer_type := layer.get_layer_type()
|
||||||
# Do not make any changes when its the same type of layer, or a group layer
|
# Do not make any changes when its the same type of layer, or a group layer
|
||||||
if layer_type == _curr_layer_type or layer_type == Global.LayerTypes.GROUP:
|
if (
|
||||||
|
layer_type == _curr_layer_type
|
||||||
|
or layer_type in [Global.LayerTypes.GROUP, Global.LayerTypes.AUDIO]
|
||||||
|
):
|
||||||
return
|
return
|
||||||
_show_relevant_tools(layer_type)
|
_show_relevant_tools(layer_type)
|
||||||
|
|
||||||
|
|
18
src/Classes/Cels/AudioCel.gd
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
class_name AudioCel
|
||||||
|
extends BaseCel
|
||||||
|
## A class for the properties of cels in AudioLayers.
|
||||||
|
## The term "cel" comes from "celluloid" (https://en.wikipedia.org/wiki/Cel).
|
||||||
|
|
||||||
|
|
||||||
|
func _init(_opacity := 1.0) -> void:
|
||||||
|
opacity = _opacity
|
||||||
|
image_texture = ImageTexture.new()
|
||||||
|
|
||||||
|
|
||||||
|
func get_image() -> Image:
|
||||||
|
var image := Global.current_project.new_empty_image()
|
||||||
|
return image
|
||||||
|
|
||||||
|
|
||||||
|
func get_class_name() -> String:
|
||||||
|
return "AudioCel"
|
|
@ -24,6 +24,13 @@ func get_final_opacity(layer: BaseLayer) -> float:
|
||||||
return layer.opacity * opacity
|
return layer.opacity * opacity
|
||||||
|
|
||||||
|
|
||||||
|
func get_frame(project: Project) -> Frame:
|
||||||
|
for frame in project.frames:
|
||||||
|
if frame.cels.has(self):
|
||||||
|
return frame
|
||||||
|
return null
|
||||||
|
|
||||||
|
|
||||||
# Methods to Override:
|
# Methods to Override:
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,7 +74,7 @@ func get_image() -> Image:
|
||||||
|
|
||||||
|
|
||||||
## Used to update the texture of the cel.
|
## Used to update the texture of the cel.
|
||||||
func update_texture() -> void:
|
func update_texture(_undo := false) -> void:
|
||||||
texture_changed.emit()
|
texture_changed.emit()
|
||||||
if link_set != null:
|
if link_set != null:
|
||||||
var frame := Global.current_project.current_frame
|
var frame := Global.current_project.current_frame
|
||||||
|
@ -92,6 +99,10 @@ func deserialize(dict: Dictionary) -> void:
|
||||||
user_data = dict.get("user_data", user_data)
|
user_data = dict.get("user_data", user_data)
|
||||||
|
|
||||||
|
|
||||||
|
func size_changed(_new_size: Vector2i) -> void:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
## Used to perform cleanup after a cel is removed.
|
## Used to perform cleanup after a cel is removed.
|
||||||
func on_remove() -> void:
|
func on_remove() -> void:
|
||||||
pass
|
pass
|
||||||
|
|
710
src/Classes/Cels/CelTileMap.gd
Normal file
|
@ -0,0 +1,710 @@
|
||||||
|
# gdlint: ignore=max-public-methods
|
||||||
|
class_name CelTileMap
|
||||||
|
extends PixelCel
|
||||||
|
|
||||||
|
## A cel type for 2D tile-based maps.
|
||||||
|
## A Tilemap cel uses a [TileSetCustom], which it inherits from its [LayerTileMap].
|
||||||
|
## Extending from [PixelCel], it contains an internal [Image], which is divided in
|
||||||
|
## grid cells, the size of which comes from [member TileSetCustom.tile_size].
|
||||||
|
## Each cell contains an index, which is an integer used to map that portion of the
|
||||||
|
## internal [member PixelCel.image] to a tile in [member tileset], as well as
|
||||||
|
## information that specifies if that cell has a transformation applied to it,
|
||||||
|
## such as horizontal flipping, vertical flipping, or if it's transposed.
|
||||||
|
|
||||||
|
## The [TileSetCustom] that this cel uses, passed down from the cel's [LayerTileMap].
|
||||||
|
var tileset: TileSetCustom
|
||||||
|
|
||||||
|
## The [Array] of type [CelTileMap.Cell] that contains data for each cell of the tilemap.
|
||||||
|
## The array's size is equal to [member horizontal_cells] * [member vertical_cells].
|
||||||
|
var cells: Array[Cell]
|
||||||
|
## The amount of horizontal cells.
|
||||||
|
var horizontal_cells: int
|
||||||
|
## The amount of vertical cells.
|
||||||
|
var vertical_cells: int
|
||||||
|
## Dictionary of [int] and [Array].
|
||||||
|
## The key is the index of the tile in the tileset,
|
||||||
|
## and the value is the index of the tilemap tile that changed first, along with
|
||||||
|
## its image that is being changed when manual mode is enabled.
|
||||||
|
## Gets reset on [method update_tilemap].
|
||||||
|
var editing_images := {}
|
||||||
|
|
||||||
|
|
||||||
|
## An internal class of [CelTIleMap], which contains data used by individual cells of the tilemap.
|
||||||
|
class Cell:
|
||||||
|
## The index of the [TileSetCustom] tile that the cell is mapped to.
|
||||||
|
var index := 0
|
||||||
|
## If [code]true[/code], the tile is flipped horizontally in this cell.
|
||||||
|
var flip_h := false
|
||||||
|
## If [code]true[/code], the tile is flipped vertically in this cell.
|
||||||
|
var flip_v := false
|
||||||
|
## If [code]true[/code], the tile is rotated 90 degrees counter-clockwise,
|
||||||
|
## and then flipped vertically in this cell.
|
||||||
|
var transpose := false
|
||||||
|
|
||||||
|
func _to_string() -> String:
|
||||||
|
var text := str(index)
|
||||||
|
if flip_h:
|
||||||
|
text += "H"
|
||||||
|
if flip_v:
|
||||||
|
text += "V"
|
||||||
|
if transpose:
|
||||||
|
text += "T"
|
||||||
|
return text
|
||||||
|
|
||||||
|
func remove_transformations() -> void:
|
||||||
|
flip_h = false
|
||||||
|
flip_v = false
|
||||||
|
transpose = false
|
||||||
|
|
||||||
|
func serialize() -> Dictionary:
|
||||||
|
return {"index": index, "flip_h": flip_h, "flip_v": flip_v, "transpose": transpose}
|
||||||
|
|
||||||
|
func deserialize(dict: Dictionary) -> void:
|
||||||
|
index = dict.get("index", index)
|
||||||
|
flip_h = dict.get("flip_h", flip_h)
|
||||||
|
flip_v = dict.get("flip_v", flip_v)
|
||||||
|
transpose = dict.get("transpose", transpose)
|
||||||
|
|
||||||
|
|
||||||
|
func _init(_tileset: TileSetCustom, _image := ImageExtended.new(), _opacity := 1.0) -> void:
|
||||||
|
super._init(_image, _opacity)
|
||||||
|
set_tileset(_tileset)
|
||||||
|
|
||||||
|
|
||||||
|
func set_tileset(new_tileset: TileSetCustom, reset_indices := true) -> void:
|
||||||
|
if tileset == new_tileset:
|
||||||
|
return
|
||||||
|
if is_instance_valid(tileset):
|
||||||
|
if tileset.updated.is_connected(_on_tileset_updated):
|
||||||
|
tileset.updated.disconnect(_on_tileset_updated)
|
||||||
|
tileset = new_tileset
|
||||||
|
if is_instance_valid(tileset):
|
||||||
|
_resize_cells(get_image().get_size(), reset_indices)
|
||||||
|
if not tileset.updated.is_connected(_on_tileset_updated):
|
||||||
|
tileset.updated.connect(_on_tileset_updated)
|
||||||
|
|
||||||
|
|
||||||
|
## Maps the cell at position [param cell_position] to
|
||||||
|
## the [member tileset]'s tile of index [param index].
|
||||||
|
func set_index(cell_position: int, index: int) -> void:
|
||||||
|
index = clampi(index, 0, tileset.tiles.size() - 1)
|
||||||
|
var previous_index := cells[cell_position].index
|
||||||
|
|
||||||
|
if previous_index != index:
|
||||||
|
if previous_index > 0 and previous_index < tileset.tiles.size():
|
||||||
|
tileset.tiles[previous_index].times_used -= 1
|
||||||
|
tileset.tiles[index].times_used += 1
|
||||||
|
cells[cell_position].index = index
|
||||||
|
cells[cell_position].flip_h = TileSetPanel.is_flipped_h
|
||||||
|
cells[cell_position].flip_v = TileSetPanel.is_flipped_v
|
||||||
|
cells[cell_position].transpose = TileSetPanel.is_transposed
|
||||||
|
_update_cell(cell_position)
|
||||||
|
Global.canvas.queue_redraw()
|
||||||
|
|
||||||
|
|
||||||
|
## Returns the pixel coordinates of the tilemap's cell
|
||||||
|
## at position [cell_position] in the cel's image.
|
||||||
|
## The reverse of [method get_cell_position].
|
||||||
|
func get_cell_coords_in_image(cell_position: int) -> Vector2i:
|
||||||
|
var x_coord := float(tileset.tile_size.x) * (cell_position % horizontal_cells)
|
||||||
|
@warning_ignore("integer_division")
|
||||||
|
var y_coord := float(tileset.tile_size.y) * (cell_position / horizontal_cells)
|
||||||
|
return Vector2i(x_coord, y_coord)
|
||||||
|
|
||||||
|
|
||||||
|
## Returns the position of a cell in the tilemap
|
||||||
|
## at pixel coordinates [param coords] in the cel's image.
|
||||||
|
## The reverse of [method get_cell_coords_in_image].
|
||||||
|
func get_cell_position(coords: Vector2i) -> int:
|
||||||
|
@warning_ignore("integer_division")
|
||||||
|
var x := coords.x / tileset.tile_size.x
|
||||||
|
x = clampi(x, 0, horizontal_cells - 1)
|
||||||
|
@warning_ignore("integer_division")
|
||||||
|
var y := coords.y / tileset.tile_size.y
|
||||||
|
y = clampi(y, 0, vertical_cells - 1)
|
||||||
|
y *= horizontal_cells
|
||||||
|
return x + y
|
||||||
|
|
||||||
|
|
||||||
|
## Returns the position of a cell in the tilemap
|
||||||
|
## at tilemap coordinates [param coords] in the cel's image.
|
||||||
|
func get_cell_position_in_tilemap_space(coords: Vector2i) -> int:
|
||||||
|
var x := coords.x
|
||||||
|
x = clampi(x, 0, horizontal_cells - 1)
|
||||||
|
var y := coords.y
|
||||||
|
y = clampi(y, 0, vertical_cells - 1)
|
||||||
|
y *= horizontal_cells
|
||||||
|
return x + y
|
||||||
|
|
||||||
|
|
||||||
|
## Returns the index of a cell in the tilemap
|
||||||
|
## at pixel coordinates [param coords] in the cel's image.
|
||||||
|
func get_cell_index_at_coords(coords: Vector2i) -> int:
|
||||||
|
return cells[get_cell_position(coords)].index
|
||||||
|
|
||||||
|
|
||||||
|
## Returns the index of a cell in the tilemap
|
||||||
|
## at tilemap coordinates [param coords] in the cel's image.
|
||||||
|
func get_cell_index_at_coords_in_tilemap_space(coords: Vector2i) -> int:
|
||||||
|
return cells[get_cell_position_in_tilemap_space(coords)].index
|
||||||
|
|
||||||
|
|
||||||
|
## Returns [code]true[/code] if the tile at cell position [param cell_position]
|
||||||
|
## with image [param image_portion] is equal to [param tile_image].
|
||||||
|
func _tiles_equal(cell_position: int, image_portion: Image, tile_image: Image) -> bool:
|
||||||
|
var cell_data := cells[cell_position]
|
||||||
|
var final_image_portion := transform_tile(
|
||||||
|
tile_image, cell_data.flip_h, cell_data.flip_v, cell_data.transpose
|
||||||
|
)
|
||||||
|
return image_portion.get_data() == final_image_portion.get_data()
|
||||||
|
|
||||||
|
|
||||||
|
## Applies transformations to [param tile_image] based on [param flip_h],
|
||||||
|
## [param flip_v] and [param transpose], and returns the transformed image.
|
||||||
|
## If [param reverse] is [code]true[/code], the transposition is applied the reverse way.
|
||||||
|
func transform_tile(
|
||||||
|
tile_image: Image, flip_h: bool, flip_v: bool, transpose: bool, reverse := false
|
||||||
|
) -> Image:
|
||||||
|
var transformed_tile := Image.new()
|
||||||
|
transformed_tile.copy_from(tile_image)
|
||||||
|
if transpose:
|
||||||
|
var tmp_image := Image.new()
|
||||||
|
tmp_image.copy_from(transformed_tile)
|
||||||
|
if reverse:
|
||||||
|
tmp_image.rotate_90(CLOCKWISE)
|
||||||
|
else:
|
||||||
|
tmp_image.rotate_90(COUNTERCLOCKWISE)
|
||||||
|
transformed_tile.blit_rect(
|
||||||
|
tmp_image, Rect2i(Vector2i.ZERO, transformed_tile.get_size()), Vector2i.ZERO
|
||||||
|
)
|
||||||
|
if reverse and not (flip_h != flip_v):
|
||||||
|
transformed_tile.flip_x()
|
||||||
|
else:
|
||||||
|
transformed_tile.flip_y()
|
||||||
|
if flip_h:
|
||||||
|
transformed_tile.flip_x()
|
||||||
|
if flip_v:
|
||||||
|
transformed_tile.flip_y()
|
||||||
|
return transformed_tile
|
||||||
|
|
||||||
|
|
||||||
|
## Given a [param selection_map] and a [param selection_rect],
|
||||||
|
## the method finds the cells that are currently selected and returns them
|
||||||
|
## in the form of a 2D array that contains the serialiazed data
|
||||||
|
##of the selected cells in the form of [Dictionary].
|
||||||
|
func get_selected_cells(selection_map: SelectionMap, selection_rect: Rect2i) -> Array[Array]:
|
||||||
|
var selected_cells: Array[Array] = []
|
||||||
|
for x in range(0, selection_rect.size.x, tileset.tile_size.x):
|
||||||
|
selected_cells.append([])
|
||||||
|
for y in range(0, selection_rect.size.y, tileset.tile_size.y):
|
||||||
|
var pos := Vector2i(x, y) + selection_rect.position
|
||||||
|
var x_index := x / tileset.tile_size.x
|
||||||
|
if selection_map.is_pixel_selected(pos):
|
||||||
|
var cell_pos := get_cell_position(pos)
|
||||||
|
selected_cells[x_index].append(cells[cell_pos].serialize())
|
||||||
|
else:
|
||||||
|
# If it's not selected, append the transparent tile 0.
|
||||||
|
selected_cells[x_index].append(
|
||||||
|
{"index": 0, "flip_h": false, "flip_v": false, "transpose": false}
|
||||||
|
)
|
||||||
|
return selected_cells
|
||||||
|
|
||||||
|
|
||||||
|
## Resizes [param selected_indices], which is an array of arrays of [Dictionary],
|
||||||
|
## to [param horizontal_size] and [param vertical_size].
|
||||||
|
## This method is used when resizing a selection and draw tiles mode is enabled.
|
||||||
|
func resize_selection(
|
||||||
|
selected_cells: Array[Array], horizontal_size: int, vertical_size: int
|
||||||
|
) -> Array[Array]:
|
||||||
|
var resized_cells: Array[Array] = []
|
||||||
|
var current_columns := selected_cells.size()
|
||||||
|
if current_columns == 0:
|
||||||
|
return resized_cells
|
||||||
|
var current_rows := selected_cells[0].size()
|
||||||
|
if current_rows == 0:
|
||||||
|
return resized_cells
|
||||||
|
resized_cells.resize(horizontal_size)
|
||||||
|
for x in horizontal_size:
|
||||||
|
resized_cells[x] = []
|
||||||
|
resized_cells[x].resize(vertical_size)
|
||||||
|
var column_middles := current_columns - 2
|
||||||
|
if current_columns == 1:
|
||||||
|
for x in horizontal_size:
|
||||||
|
_resize_rows(selected_cells[0], resized_cells[x], current_rows, vertical_size)
|
||||||
|
else:
|
||||||
|
for x in horizontal_size:
|
||||||
|
if x == 0:
|
||||||
|
_resize_rows(selected_cells[0], resized_cells[x], current_rows, vertical_size)
|
||||||
|
elif x == horizontal_size - 1:
|
||||||
|
_resize_rows(selected_cells[-1], resized_cells[x], current_rows, vertical_size)
|
||||||
|
else:
|
||||||
|
if x < current_columns - 1:
|
||||||
|
_resize_rows(selected_cells[x], resized_cells[x], current_rows, vertical_size)
|
||||||
|
else:
|
||||||
|
if column_middles == 0:
|
||||||
|
_resize_rows(
|
||||||
|
selected_cells[-1], resized_cells[x], current_rows, vertical_size
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
var x_index := x - (column_middles * ((x - 1) / column_middles))
|
||||||
|
_resize_rows(
|
||||||
|
selected_cells[x_index], resized_cells[x], current_rows, vertical_size
|
||||||
|
)
|
||||||
|
return resized_cells
|
||||||
|
|
||||||
|
|
||||||
|
## Helper method of [method resize_selection].
|
||||||
|
func _resize_rows(
|
||||||
|
selected_cells: Array, resized_cells: Array, current_rows: int, vertical_size: int
|
||||||
|
) -> void:
|
||||||
|
var row_middles := current_rows - 2
|
||||||
|
if current_rows == 1:
|
||||||
|
for y in vertical_size:
|
||||||
|
resized_cells[y] = selected_cells[0]
|
||||||
|
else:
|
||||||
|
for y in vertical_size:
|
||||||
|
if y == 0:
|
||||||
|
resized_cells[y] = selected_cells[0]
|
||||||
|
elif y == vertical_size - 1:
|
||||||
|
resized_cells[y] = selected_cells[-1]
|
||||||
|
else:
|
||||||
|
if y < current_rows - 1:
|
||||||
|
resized_cells[y] = selected_cells[y]
|
||||||
|
else:
|
||||||
|
if row_middles == 0:
|
||||||
|
resized_cells[y] = selected_cells[-1]
|
||||||
|
else:
|
||||||
|
var y_index := y - (row_middles * ((y - 1) / row_middles))
|
||||||
|
resized_cells[y] = selected_cells[y_index]
|
||||||
|
|
||||||
|
|
||||||
|
## Applies the [param selected_cells] data to [param target_image] data,
|
||||||
|
## offset by [param selection_rect]. The target image needs to be resized first.
|
||||||
|
## This method is used when resizing a selection and draw tiles mode is enabled.
|
||||||
|
func apply_resizing_to_image(
|
||||||
|
target_image: Image, selected_cells: Array[Array], selection_rect: Rect2i
|
||||||
|
) -> void:
|
||||||
|
for x in selected_cells.size():
|
||||||
|
for y in selected_cells[x].size():
|
||||||
|
var pos := Vector2i(x, y) * tileset.tile_size + selection_rect.position
|
||||||
|
var cell_pos := get_cell_position(pos)
|
||||||
|
var coords := get_cell_coords_in_image(cell_pos) - selection_rect.position
|
||||||
|
var rect := Rect2i(coords, tileset.tile_size)
|
||||||
|
var image_portion := target_image.get_region(rect)
|
||||||
|
var cell_data := Cell.new()
|
||||||
|
cell_data.deserialize(selected_cells[x][y])
|
||||||
|
var index := cell_data.index
|
||||||
|
if index >= tileset.tiles.size():
|
||||||
|
index = 0
|
||||||
|
var current_tile := tileset.tiles[index].image
|
||||||
|
var transformed_tile := transform_tile(
|
||||||
|
current_tile, cell_data.flip_h, cell_data.flip_v, cell_data.transpose
|
||||||
|
)
|
||||||
|
if image_portion.get_data() != transformed_tile.get_data():
|
||||||
|
var tile_size := transformed_tile.get_size()
|
||||||
|
target_image.blit_rect(transformed_tile, Rect2i(Vector2i.ZERO, tile_size), coords)
|
||||||
|
if target_image is ImageExtended:
|
||||||
|
target_image.convert_rgb_to_indexed()
|
||||||
|
|
||||||
|
|
||||||
|
## Appends data to a [Dictionary] to be used for undo/redo.
|
||||||
|
func serialize_undo_data() -> Dictionary:
|
||||||
|
var dict := {}
|
||||||
|
var cell_indices := []
|
||||||
|
cell_indices.resize(cells.size())
|
||||||
|
for i in cell_indices.size():
|
||||||
|
cell_indices[i] = cells[i].serialize()
|
||||||
|
dict["cell_indices"] = cell_indices
|
||||||
|
dict["tileset"] = tileset.serialize_undo_data()
|
||||||
|
dict["resize"] = false
|
||||||
|
return dict
|
||||||
|
|
||||||
|
|
||||||
|
## Same purpose as [method serialize_undo_data], but for when the image resource
|
||||||
|
## ([param source_image]) we want to store to the undo/redo stack
|
||||||
|
## is not the same as [member image]. This method also handles the resizing logic for undo/redo.
|
||||||
|
func serialize_undo_data_source_image(
|
||||||
|
source_image: ImageExtended, redo_data: Dictionary, undo_data: Dictionary
|
||||||
|
) -> void:
|
||||||
|
undo_data[self] = serialize_undo_data()
|
||||||
|
if source_image.get_size() != image.get_size():
|
||||||
|
undo_data[self]["resize"] = true
|
||||||
|
_resize_cells(source_image.get_size())
|
||||||
|
tileset.clear_tileset(self)
|
||||||
|
var tile_editing_mode := TileSetPanel.tile_editing_mode
|
||||||
|
if tile_editing_mode == TileSetPanel.TileEditingMode.MANUAL:
|
||||||
|
tile_editing_mode = TileSetPanel.TileEditingMode.AUTO
|
||||||
|
update_tilemap(tile_editing_mode, source_image)
|
||||||
|
redo_data[self] = serialize_undo_data()
|
||||||
|
redo_data[self]["resize"] = undo_data[self]["resize"]
|
||||||
|
|
||||||
|
|
||||||
|
## Reads data from a [param dict] [Dictionary], and uses them to add methods to [param undo_redo].
|
||||||
|
func deserialize_undo_data(dict: Dictionary, undo_redo: UndoRedo, undo: bool) -> void:
|
||||||
|
var cell_indices = dict.cell_indices
|
||||||
|
if undo:
|
||||||
|
undo_redo.add_undo_method(_deserialize_cell_data.bind(cell_indices, dict.resize))
|
||||||
|
if dict.has("tileset"):
|
||||||
|
undo_redo.add_undo_method(tileset.deserialize_undo_data.bind(dict.tileset, self))
|
||||||
|
else:
|
||||||
|
undo_redo.add_do_method(_deserialize_cell_data.bind(cell_indices, dict.resize))
|
||||||
|
if dict.has("tileset"):
|
||||||
|
undo_redo.add_do_method(tileset.deserialize_undo_data.bind(dict.tileset, self))
|
||||||
|
|
||||||
|
|
||||||
|
## Gets called every time a change is being applied to the [param image],
|
||||||
|
## such as when finishing drawing with a draw tool, or when applying an image effect.
|
||||||
|
## This method responsible for updating the indices of the [member cells], as well as
|
||||||
|
## updating the [member tileset] with the incoming changes.
|
||||||
|
## The updating behavior depends on the current tile editing mode
|
||||||
|
## by [member TileSetPanel.tile_editing_mode].
|
||||||
|
## If a [param source_image] is provided, that image is being used instead of [member image].
|
||||||
|
func update_tilemap(
|
||||||
|
tile_editing_mode := TileSetPanel.tile_editing_mode, source_image := image
|
||||||
|
) -> void:
|
||||||
|
editing_images.clear()
|
||||||
|
var tileset_size_before_update := tileset.tiles.size()
|
||||||
|
for i in cells.size():
|
||||||
|
var coords := get_cell_coords_in_image(i)
|
||||||
|
var rect := Rect2i(coords, tileset.tile_size)
|
||||||
|
var image_portion := source_image.get_region(rect)
|
||||||
|
var index := cells[i].index
|
||||||
|
if index >= tileset.tiles.size():
|
||||||
|
index = 0
|
||||||
|
var current_tile := tileset.tiles[index]
|
||||||
|
if tile_editing_mode == TileSetPanel.TileEditingMode.MANUAL:
|
||||||
|
if image_portion.is_invisible():
|
||||||
|
continue
|
||||||
|
if index == 0:
|
||||||
|
# If the tileset is empty, only then add a new tile.
|
||||||
|
if tileset.tiles.size() <= 1:
|
||||||
|
tileset.add_tile(image_portion, self)
|
||||||
|
cells[i].index = tileset.tiles.size() - 1
|
||||||
|
continue
|
||||||
|
if not _tiles_equal(i, image_portion, current_tile.image):
|
||||||
|
tileset.replace_tile_at(image_portion, index, self)
|
||||||
|
elif tile_editing_mode == TileSetPanel.TileEditingMode.AUTO:
|
||||||
|
_handle_auto_editing_mode(i, image_portion, tileset_size_before_update)
|
||||||
|
else: # Stack
|
||||||
|
if image_portion.is_invisible():
|
||||||
|
continue
|
||||||
|
var found_tile := false
|
||||||
|
for j in range(1, tileset.tiles.size()):
|
||||||
|
var tile := tileset.tiles[j]
|
||||||
|
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
|
||||||
|
if not found_tile:
|
||||||
|
tileset.add_tile(image_portion, self)
|
||||||
|
cells[i].index = tileset.tiles.size() - 1
|
||||||
|
cells[i].remove_transformations()
|
||||||
|
# Updates transparent cells that have indices higher than 0.
|
||||||
|
# This can happen when switching to another tileset which has less tiles
|
||||||
|
# than the previous one.
|
||||||
|
for i in cells.size():
|
||||||
|
var coords := get_cell_coords_in_image(i)
|
||||||
|
var rect := Rect2i(coords, tileset.tile_size)
|
||||||
|
var image_portion := source_image.get_region(rect)
|
||||||
|
if not image_portion.is_invisible():
|
||||||
|
continue
|
||||||
|
var index := cells[i].index
|
||||||
|
if index == 0:
|
||||||
|
continue
|
||||||
|
if index >= tileset.tiles.size():
|
||||||
|
index = 0
|
||||||
|
var current_tile := tileset.tiles[index]
|
||||||
|
if not _tiles_equal(i, image_portion, current_tile.image):
|
||||||
|
set_index(i, cells[i].index)
|
||||||
|
|
||||||
|
|
||||||
|
## Gets called by [method update_tilemap]. This method is responsible for handling
|
||||||
|
## the tilemap updating behavior for the auto tile editing mode.[br]
|
||||||
|
## Cases:[br]
|
||||||
|
## 0) Cell is transparent. Set its index to 0.
|
||||||
|
## [br]
|
||||||
|
## 0.5) Cell is transparent and mapped.
|
||||||
|
## Set its index to 0 and unuse the mapped tile.
|
||||||
|
## If the mapped tile is removed, reduce the index of all cells that have
|
||||||
|
## indices greater or equal than the existing tile's index.
|
||||||
|
## [br]
|
||||||
|
## 1) Cell not mapped, exists in the tileset.
|
||||||
|
## Map the cell to the existing tile and increase its times_used by one.
|
||||||
|
## [br]
|
||||||
|
## 2) Cell not mapped, does not exist in the tileset.
|
||||||
|
## Add the cell as a tile in the tileset, set its index to be the tileset's tile size - 1.
|
||||||
|
## [br]
|
||||||
|
## 3) Cell mapped, tile did not change. Do nothing.
|
||||||
|
## [br]
|
||||||
|
## 4) Cell mapped, exists in the tileset.
|
||||||
|
## The mapped tile still exists in the tileset.
|
||||||
|
## Map the cell to the existing tile, increase its times_used by one,
|
||||||
|
## and reduce the previously mapped tile's times_used by 1.
|
||||||
|
## [br]
|
||||||
|
## 5) Cell mapped, exists in the tileset.
|
||||||
|
## The mapped tile does not exist in the tileset anymore.
|
||||||
|
## Map the cell to the existing tile and increase its times_used by one.
|
||||||
|
## Remove the previously mapped tile,
|
||||||
|
## and reduce the index of all cells that have indices greater or equal
|
||||||
|
## than the existing tile's index.
|
||||||
|
## [br]
|
||||||
|
## 6) Cell mapped, does not exist in the tileset.
|
||||||
|
## The mapped tile still exists in the tileset.
|
||||||
|
## Add the cell as a tile in the tileset, set its index to be the tileset's tile size - 1.
|
||||||
|
## Reduce the previously mapped tile's times_used by 1.
|
||||||
|
## [br]
|
||||||
|
## 7) Cell mapped, does not exist in the tileset.
|
||||||
|
## The mapped tile does not exist in the tileset anymore.
|
||||||
|
## Simply replace the old tile with the new one, do not change its index.
|
||||||
|
func _handle_auto_editing_mode(
|
||||||
|
i: int, image_portion: Image, tileset_size_before_update: int
|
||||||
|
) -> void:
|
||||||
|
var index := cells[i].index
|
||||||
|
if index >= tileset.tiles.size():
|
||||||
|
index = 0
|
||||||
|
var current_tile := tileset.tiles[index]
|
||||||
|
if image_portion.is_invisible():
|
||||||
|
# Case 0: The cell is transparent.
|
||||||
|
if cells[i].index >= tileset_size_before_update:
|
||||||
|
return
|
||||||
|
cells[i].index = 0
|
||||||
|
cells[i].remove_transformations()
|
||||||
|
if index > 0:
|
||||||
|
# Case 0.5: The cell is transparent and mapped to a tile.
|
||||||
|
var is_removed := tileset.unuse_tile_at_index(index, self)
|
||||||
|
if is_removed:
|
||||||
|
# Re-index all indices that are after the deleted one.
|
||||||
|
_re_index_cells_after_index(index)
|
||||||
|
return
|
||||||
|
var index_in_tileset := tileset.find_tile(image_portion)
|
||||||
|
if index == 0: # If the cell is not mapped to a tile.
|
||||||
|
if index_in_tileset > -1:
|
||||||
|
# Case 1: The cell is not mapped already,
|
||||||
|
# and it exists in the tileset as a tile.
|
||||||
|
tileset.tiles[index_in_tileset].times_used += 1
|
||||||
|
cells[i].index = index_in_tileset
|
||||||
|
else:
|
||||||
|
# Case 2: The cell is not mapped already,
|
||||||
|
# and it does not exist in the tileset.
|
||||||
|
tileset.add_tile(image_portion, self)
|
||||||
|
cells[i].index = tileset.tiles.size() - 1
|
||||||
|
else: # If the cell is already mapped.
|
||||||
|
if _tiles_equal(i, image_portion, current_tile.image):
|
||||||
|
# Case 3: The cell is mapped and it did not change.
|
||||||
|
# Do nothing and move on to the next cell.
|
||||||
|
return
|
||||||
|
if index_in_tileset > -1: # If the cell exists in the tileset as a tile.
|
||||||
|
if current_tile.times_used > 1:
|
||||||
|
# Case 4: The cell is mapped and it exists in the tileset as a tile,
|
||||||
|
# and the currently mapped tile still exists in the tileset.
|
||||||
|
tileset.tiles[index_in_tileset].times_used += 1
|
||||||
|
cells[i].index = index_in_tileset
|
||||||
|
tileset.unuse_tile_at_index(index, self)
|
||||||
|
else:
|
||||||
|
# Case 5: The cell is mapped and it exists in the tileset as a tile,
|
||||||
|
# and the currently mapped tile no longer exists in the tileset.
|
||||||
|
tileset.tiles[index_in_tileset].times_used += 1
|
||||||
|
cells[i].index = index_in_tileset
|
||||||
|
tileset.remove_tile_at_index(index, self)
|
||||||
|
# Re-index all indices that are after the deleted one.
|
||||||
|
_re_index_cells_after_index(index)
|
||||||
|
else: # If the cell does not exist in the tileset as a tile.
|
||||||
|
if current_tile.times_used > 1:
|
||||||
|
# Case 6: The cell is mapped and it does not
|
||||||
|
# exist in the tileset as a tile,
|
||||||
|
# and the currently mapped tile still exists in the tileset.
|
||||||
|
tileset.unuse_tile_at_index(index, self)
|
||||||
|
tileset.add_tile(image_portion, self)
|
||||||
|
cells[i].index = tileset.tiles.size() - 1
|
||||||
|
else:
|
||||||
|
# Case 7: The cell is mapped and it does not
|
||||||
|
# exist in the tileset as a tile,
|
||||||
|
# and the currently mapped tile no longer exists in the tileset.
|
||||||
|
tileset.replace_tile_at(image_portion, index, self)
|
||||||
|
cells[i].remove_transformations()
|
||||||
|
|
||||||
|
|
||||||
|
## Re-indexes all [member cells] that are larger or equal to [param index],
|
||||||
|
## by reducing their value by one.
|
||||||
|
func _re_index_cells_after_index(index: int) -> void:
|
||||||
|
for i in cells.size():
|
||||||
|
var tmp_index := cells[i].index
|
||||||
|
if tmp_index >= index:
|
||||||
|
cells[i].index -= 1
|
||||||
|
|
||||||
|
|
||||||
|
## Updates the [member image] data of the cell of the tilemap in [param cell_position],
|
||||||
|
## to ensure that it is the same as its mapped tile in the [member tileset].
|
||||||
|
func _update_cell(cell_position: int) -> void:
|
||||||
|
var coords := get_cell_coords_in_image(cell_position)
|
||||||
|
var rect := Rect2i(coords, tileset.tile_size)
|
||||||
|
var image_portion := image.get_region(rect)
|
||||||
|
var cell_data := cells[cell_position]
|
||||||
|
var index := cell_data.index
|
||||||
|
if index >= tileset.tiles.size():
|
||||||
|
index = 0
|
||||||
|
var current_tile := tileset.tiles[index].image
|
||||||
|
var transformed_tile := transform_tile(
|
||||||
|
current_tile, cell_data.flip_h, cell_data.flip_v, cell_data.transpose
|
||||||
|
)
|
||||||
|
if image_portion.get_data() != transformed_tile.get_data():
|
||||||
|
var tile_size := transformed_tile.get_size()
|
||||||
|
image.blit_rect(transformed_tile, Rect2i(Vector2i.ZERO, tile_size), coords)
|
||||||
|
image.convert_rgb_to_indexed()
|
||||||
|
|
||||||
|
|
||||||
|
## Calls [method _update_cell] for all [member cells].
|
||||||
|
func update_cel_portions() -> void:
|
||||||
|
for i in cells.size():
|
||||||
|
_update_cell(i)
|
||||||
|
|
||||||
|
|
||||||
|
## Loops through all [member cells] of the tilemap and updates their indices,
|
||||||
|
## so they can remain mapped to the [member tileset]'s tiles.
|
||||||
|
func _re_index_all_cells() -> void:
|
||||||
|
for i in cells.size():
|
||||||
|
var coords := get_cell_coords_in_image(i)
|
||||||
|
var rect := Rect2i(coords, tileset.tile_size)
|
||||||
|
var image_portion := image.get_region(rect)
|
||||||
|
if image_portion.is_invisible():
|
||||||
|
var index := cells[i].index
|
||||||
|
if index > 0 and index < tileset.tiles.size():
|
||||||
|
var current_tile := tileset.tiles[index]
|
||||||
|
if not _tiles_equal(i, image_portion, current_tile.image):
|
||||||
|
set_index(i, cells[i].index)
|
||||||
|
continue
|
||||||
|
for j in range(1, tileset.tiles.size()):
|
||||||
|
var tile := tileset.tiles[j]
|
||||||
|
if _tiles_equal(i, image_portion, tile.image):
|
||||||
|
cells[i].index = j
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
## Resizes the [member cells] array based on [param new_size].
|
||||||
|
func _resize_cells(new_size: Vector2i, reset_indices := true) -> void:
|
||||||
|
horizontal_cells = ceili(float(new_size.x) / tileset.tile_size.x)
|
||||||
|
vertical_cells = ceili(float(new_size.y) / tileset.tile_size.y)
|
||||||
|
cells.resize(horizontal_cells * vertical_cells)
|
||||||
|
for i in cells.size():
|
||||||
|
if reset_indices:
|
||||||
|
cells[i] = Cell.new()
|
||||||
|
else:
|
||||||
|
if not is_instance_valid(cells[i]):
|
||||||
|
cells[i] = Cell.new()
|
||||||
|
|
||||||
|
|
||||||
|
## Returns [code]true[/code] if the user just did a Redo.
|
||||||
|
func _is_redo() -> bool:
|
||||||
|
return Global.control.redone
|
||||||
|
|
||||||
|
|
||||||
|
## If the tileset has been modified by another [param cel],
|
||||||
|
## make sure to also update it here.
|
||||||
|
## If [param replace_index] is larger than -1, it means that manual mode
|
||||||
|
## has been used to replace a tile in the tileset in another cel,
|
||||||
|
## so call [method update_cel_portions] to update it in this cel as well.
|
||||||
|
## Otherwise, call [method _re_index_all_cells] to ensure that the cells have correct indices.
|
||||||
|
func _on_tileset_updated(cel: CelTileMap, replace_index: int) -> void:
|
||||||
|
if cel == self or not is_instance_valid(cel):
|
||||||
|
return
|
||||||
|
if link_set != null and cel in link_set["cels"]:
|
||||||
|
return
|
||||||
|
if replace_index > -1: # Manual mode
|
||||||
|
update_cel_portions()
|
||||||
|
else:
|
||||||
|
_re_index_all_cells()
|
||||||
|
Global.canvas.update_all_layers = true
|
||||||
|
Global.canvas.queue_redraw()
|
||||||
|
|
||||||
|
|
||||||
|
func _deserialize_cell_data(cell_indices: Array, resize: bool) -> void:
|
||||||
|
if resize:
|
||||||
|
_resize_cells(image.get_size())
|
||||||
|
for i in cell_indices.size():
|
||||||
|
var cell_data: Dictionary = cell_indices[i]
|
||||||
|
cells[i].deserialize(cell_data)
|
||||||
|
|
||||||
|
|
||||||
|
# Overridden Methods:
|
||||||
|
func set_content(content, texture: ImageTexture = null) -> void:
|
||||||
|
super.set_content(content, texture)
|
||||||
|
_resize_cells(image.get_size())
|
||||||
|
_re_index_all_cells()
|
||||||
|
|
||||||
|
|
||||||
|
func update_texture(undo := false) -> void:
|
||||||
|
var tile_editing_mode := TileSetPanel.tile_editing_mode
|
||||||
|
if undo or _is_redo() or tile_editing_mode != TileSetPanel.TileEditingMode.MANUAL:
|
||||||
|
super.update_texture(undo)
|
||||||
|
editing_images.clear()
|
||||||
|
return
|
||||||
|
|
||||||
|
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)
|
||||||
|
var current_tile := tileset.tiles[index]
|
||||||
|
if index == 0:
|
||||||
|
if tileset.tiles.size() > 1:
|
||||||
|
# Prevent from drawing on empty image portions.
|
||||||
|
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:
|
||||||
|
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]
|
||||||
|
var editing_image := editing_images[index][1] as Image
|
||||||
|
var transformed_editing_image := transform_tile(
|
||||||
|
editing_image, cell_data.flip_h, cell_data.flip_v, cell_data.transpose
|
||||||
|
)
|
||||||
|
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)
|
||||||
|
super.update_texture(undo)
|
||||||
|
|
||||||
|
|
||||||
|
func serialize() -> Dictionary:
|
||||||
|
var dict := super.serialize()
|
||||||
|
var cell_indices := []
|
||||||
|
cell_indices.resize(cells.size())
|
||||||
|
for i in cell_indices.size():
|
||||||
|
cell_indices[i] = cells[i].serialize()
|
||||||
|
dict["cell_indices"] = cell_indices
|
||||||
|
return dict
|
||||||
|
|
||||||
|
|
||||||
|
func deserialize(dict: Dictionary) -> void:
|
||||||
|
super.deserialize(dict)
|
||||||
|
var cell_indices = dict.get("cell_indices")
|
||||||
|
for i in cell_indices.size():
|
||||||
|
cells[i].deserialize(cell_indices[i])
|
||||||
|
|
||||||
|
|
||||||
|
func get_class_name() -> String:
|
||||||
|
return "CelTileMap"
|
|
@ -10,9 +10,7 @@ func _init(_opacity := 1.0) -> void:
|
||||||
|
|
||||||
|
|
||||||
func get_image() -> Image:
|
func get_image() -> Image:
|
||||||
var image := Image.create(
|
var image := Global.current_project.new_empty_image()
|
||||||
Global.current_project.size.x, Global.current_project.size.y, false, Image.FORMAT_RGBA8
|
|
||||||
)
|
|
||||||
return image
|
return image
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,28 +4,34 @@ extends BaseCel
|
||||||
## The term "cel" comes from "celluloid" (https://en.wikipedia.org/wiki/Cel).
|
## The term "cel" comes from "celluloid" (https://en.wikipedia.org/wiki/Cel).
|
||||||
|
|
||||||
## This variable is where the image data of the cel are.
|
## This variable is where the image data of the cel are.
|
||||||
var image: Image:
|
var image: ImageExtended:
|
||||||
set = image_changed
|
set = image_changed
|
||||||
|
|
||||||
|
|
||||||
func _init(_image := Image.new(), _opacity := 1.0) -> void:
|
func _init(_image := ImageExtended.new(), _opacity := 1.0) -> void:
|
||||||
image_texture = ImageTexture.new()
|
image_texture = ImageTexture.new()
|
||||||
image = _image # Set image and call setter
|
image = _image # Set image and call setter
|
||||||
opacity = _opacity
|
opacity = _opacity
|
||||||
|
|
||||||
|
|
||||||
func image_changed(value: Image) -> void:
|
func image_changed(value: ImageExtended) -> void:
|
||||||
image = value
|
image = value
|
||||||
if not image.is_empty() and is_instance_valid(image_texture):
|
if not image.is_empty() and is_instance_valid(image_texture):
|
||||||
image_texture.set_image(image)
|
image_texture.set_image(image)
|
||||||
|
|
||||||
|
|
||||||
func get_content():
|
func get_content() -> ImageExtended:
|
||||||
return image
|
return image
|
||||||
|
|
||||||
|
|
||||||
func set_content(content, texture: ImageTexture = null) -> void:
|
func set_content(content, texture: ImageTexture = null) -> void:
|
||||||
image = content
|
var proper_content: ImageExtended
|
||||||
|
if content is not ImageExtended:
|
||||||
|
proper_content = ImageExtended.new()
|
||||||
|
proper_content.copy_from_custom(content, image.is_indexed)
|
||||||
|
else:
|
||||||
|
proper_content = content
|
||||||
|
image = proper_content
|
||||||
if is_instance_valid(texture) and is_instance_valid(texture.get_image()):
|
if is_instance_valid(texture) and is_instance_valid(texture.get_image()):
|
||||||
image_texture = texture
|
image_texture = texture
|
||||||
if image_texture.get_image().get_size() != image.get_size():
|
if image_texture.get_image().get_size() != image.get_size():
|
||||||
|
@ -34,27 +40,29 @@ func set_content(content, texture: ImageTexture = null) -> void:
|
||||||
image_texture.update(image)
|
image_texture.update(image)
|
||||||
|
|
||||||
|
|
||||||
func create_empty_content():
|
func create_empty_content() -> ImageExtended:
|
||||||
var empty_image := Image.create(
|
var empty := Image.create(image.get_width(), image.get_height(), false, image.get_format())
|
||||||
image.get_size().x, image.get_size().y, false, Image.FORMAT_RGBA8
|
var new_image := ImageExtended.new()
|
||||||
)
|
new_image.copy_from_custom(empty, image.is_indexed)
|
||||||
return empty_image
|
return new_image
|
||||||
|
|
||||||
|
|
||||||
func copy_content():
|
func copy_content() -> ImageExtended:
|
||||||
var copy_image := Image.create_from_data(
|
var tmp_image := Image.create_from_data(
|
||||||
image.get_width(), image.get_height(), false, Image.FORMAT_RGBA8, image.get_data()
|
image.get_width(), image.get_height(), false, image.get_format(), image.get_data()
|
||||||
)
|
)
|
||||||
|
var copy_image := ImageExtended.new()
|
||||||
|
copy_image.copy_from_custom(tmp_image, image.is_indexed)
|
||||||
return copy_image
|
return copy_image
|
||||||
|
|
||||||
|
|
||||||
func get_image() -> Image:
|
func get_image() -> ImageExtended:
|
||||||
return image
|
return image
|
||||||
|
|
||||||
|
|
||||||
func update_texture() -> void:
|
func update_texture(undo := false) -> void:
|
||||||
image_texture.set_image(image)
|
image_texture.set_image(image)
|
||||||
super.update_texture()
|
super.update_texture(undo)
|
||||||
|
|
||||||
|
|
||||||
func get_class_name() -> String:
|
func get_class_name() -> String:
|
||||||
|
|