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

Revert palette file format back to JSON (#967)

* Some static typing and use notification to check if the theme has changed in swatches

* Use Vector2i for scrolling, hide scrollbars in the node properties

* More static typing improvements

* More static typing & docstring improvements, remove some methods from Palettes.gd

* [WIP] Go back to json for palettes instead of tres

* Revert back to using dictionaries for palette colors instead of array

Reverts part of the previous commit

* Read width & height from files, don't store the name

* Fix palette renaming

* Copy non-json palettes into json files

* Fix palette duplication

* Add a new _fill_imported_palette_with_colors() to avoid duplicate code in import file methods

* Fix palette file importing when not initialising

* Export palettes as images

* Replace "tres" with "json" filter in the open sprite dialog

* When exporting a palette as an image, automatically set the file name to the palette name

* Replace default palette files with json

* Remove the Global.palette_panel variable, use signals instead.

* Static typing in signals

* Fix warning in Palettes.gd

* Fix formatting

* Add missing comments to the palette files

* Update Palettes.gd

* A few more static typing improvements
This commit is contained in:
Emmanouil Papadeas 2023-12-23 00:28:35 +02:00 committed by GitHub
parent 18a74c7b9c
commit 0cb98f6e2e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 1059 additions and 1438 deletions

View file

@ -0,0 +1,71 @@
{
"colors": [
{
"color": "(0.0824, 0.0902, 0.102, 1)",
"index": 0
},
{
"color": "(0.4941, 0.0196, 0.1294, 1)",
"index": 1
},
{
"color": "(0.8392, 0.1373, 0.0667, 1)",
"index": 2
},
{
"color": "(1, 0.5137, 0.149, 1)",
"index": 3
},
{
"color": "(1, 0.8196, 0, 1)",
"index": 4
},
{
"color": "(0.9765, 0.9922, 1, 1)",
"index": 5
},
{
"color": "(1, 0.502, 0.6392, 1)",
"index": 6
},
{
"color": "(1, 0.149, 0.4549, 1)",
"index": 7
},
{
"color": "(0.5765, 0.1294, 0.4118, 1)",
"index": 8
},
{
"color": "(0.2588, 0, 0.4039, 1)",
"index": 9
},
{
"color": "(0.1373, 0.2863, 0.4588, 1)",
"index": 10
},
{
"color": "(0.4039, 0.6824, 0.8314, 1)",
"index": 11
},
{
"color": "(0.749, 1, 0.2314, 1)",
"index": 12
},
{
"color": "(0.0627, 0.8196, 0.4588, 1)",
"index": 13
},
{
"color": "(0, 0.4667, 0.6, 1)",
"index": 14
},
{
"color": "(0, 0.1569, 0.349, 1)",
"index": 15
}
],
"comment": "Author: PineTreePizza\nFound in Lospec by CheetoHead/greusser\nhttps://lospec.com/palette-list/bubblegum-16",
"height": 2,
"width": 8
}

View file

@ -1,113 +0,0 @@
[gd_resource type="Resource" load_steps=19 format=2]
[ext_resource path="res://src/Palette/Palette.gd" type="Script" id=1]
[ext_resource path="res://src/Palette/PaletteColor.gd" type="Script" id=2]
[sub_resource type="Resource" id=1]
script = ExtResource( 2 )
color = Color( 0.0862745, 0.0901961, 0.101961, 1 )
index = 0
[sub_resource type="Resource" id=2]
script = ExtResource( 2 )
color = Color( 0.498039, 0.0235294, 0.133333, 1 )
index = 1
[sub_resource type="Resource" id=3]
script = ExtResource( 2 )
color = Color( 0.839216, 0.141176, 0.0666667, 1 )
index = 2
[sub_resource type="Resource" id=4]
script = ExtResource( 2 )
color = Color( 1, 0.517647, 0.14902, 1 )
index = 3
[sub_resource type="Resource" id=5]
script = ExtResource( 2 )
color = Color( 1, 0.819608, 0, 1 )
index = 4
[sub_resource type="Resource" id=6]
script = ExtResource( 2 )
color = Color( 0.980392, 0.992157, 1, 1 )
index = 5
[sub_resource type="Resource" id=7]
script = ExtResource( 2 )
color = Color( 1, 0.501961, 0.643137, 1 )
index = 6
[sub_resource type="Resource" id=8]
script = ExtResource( 2 )
color = Color( 1, 0.14902, 0.454902, 1 )
index = 7
[sub_resource type="Resource" id=9]
script = ExtResource( 2 )
color = Color( 0.580392, 0.129412, 0.415686, 1 )
index = 8
[sub_resource type="Resource" id=10]
script = ExtResource( 2 )
color = Color( 0.262745, 0, 0.403922, 1 )
index = 9
[sub_resource type="Resource" id=11]
script = ExtResource( 2 )
color = Color( 0.137255, 0.286275, 0.458824, 1 )
index = 10
[sub_resource type="Resource" id=12]
script = ExtResource( 2 )
color = Color( 0.407843, 0.682353, 0.831373, 1 )
index = 11
[sub_resource type="Resource" id=13]
script = ExtResource( 2 )
color = Color( 0.74902, 1, 0.235294, 1 )
index = 12
[sub_resource type="Resource" id=14]
script = ExtResource( 2 )
color = Color( 0.0627451, 0.823529, 0.458824, 1 )
index = 13
[sub_resource type="Resource" id=15]
script = ExtResource( 2 )
color = Color( 0, 0.470588, 0.6, 1 )
index = 14
[sub_resource type="Resource" id=16]
script = ExtResource( 2 )
color = Color( 0, 0.156863, 0.34902, 1 )
index = 15
[resource]
resource_name = "BubbleGum16"
script = ExtResource( 1 )
name = "BubbleGum16"
comment = "Author: PineTreePizza
Found in Lospec by CheetoHead/greusser
https://lospec.com/palette-list/bubblegum-16"
width = 8
height = 2
colors = {
0: SubResource( 1 ),
1: SubResource( 2 ),
2: SubResource( 3 ),
3: SubResource( 4 ),
4: SubResource( 5 ),
5: SubResource( 6 ),
6: SubResource( 7 ),
7: SubResource( 8 ),
8: SubResource( 9 ),
9: SubResource( 10 ),
10: SubResource( 11 ),
11: SubResource( 12 ),
12: SubResource( 13 ),
13: SubResource( 14 ),
14: SubResource( 15 ),
15: SubResource( 16 )
}
colors_max = 16

View file

@ -0,0 +1,107 @@
{
"colors": [
{
"color": "(0.702, 0.3137, 0.0078, 1)",
"index": 0
},
{
"color": "(1, 0.6, 0.2667, 1)",
"index": 1
},
{
"color": "(1, 0.4392, 0, 1)",
"index": 2
},
{
"color": "(0, 0.6, 0.702, 1)",
"index": 3
},
{
"color": "(0, 0.8549, 1, 1)",
"index": 4
},
{
"color": "(0.702, 0.0078, 0.0078, 1)",
"index": 5
},
{
"color": "(1, 0.2667, 0.2667, 1)",
"index": 6
},
{
"color": "(1, 0.0078, 0.0039, 1)",
"index": 7
},
{
"color": "(0, 0.702, 0.2, 1)",
"index": 8
},
{
"color": "(0, 1, 0.2824, 1)",
"index": 9
},
{
"color": "(0.502, 0.0078, 0.702, 1)",
"index": 10
},
{
"color": "(0.7922, 0.2667, 1, 1)",
"index": 11
},
{
"color": "(0.702, 0, 0.9922, 1)",
"index": 12
},
{
"color": "(0.4941, 0.702, 0, 1)",
"index": 13
},
{
"color": "(0.7098, 1, 0, 1)",
"index": 14
},
{
"color": "(0.0078, 0.0667, 0.702, 1)",
"index": 15
},
{
"color": "(0.2667, 0.3294, 1, 1)",
"index": 16
},
{
"color": "(0.0039, 0.0824, 1, 1)",
"index": 17
},
{
"color": "(0.702, 0.549, 0, 1)",
"index": 18
},
{
"color": "(1, 0.7843, 0, 1)",
"index": 19
},
{
"color": "(0.0078, 0.6196, 0.702, 1)",
"index": 20
},
{
"color": "(0.4745, 0.9373, 1, 1)",
"index": 21
},
{
"color": "(0, 0.8824, 1, 1)",
"index": 22
},
{
"color": "(0.702, 0.302, 0, 1)",
"index": 23
},
{
"color": "(1, 0.4314, 0, 1)",
"index": 24
}
],
"comment": "Author: Erevoid",
"height": 4,
"width": 8
}

View file

@ -1,165 +0,0 @@
[gd_resource type="Resource" load_steps=28 format=2]
[ext_resource path="res://src/Palette/Palette.gd" type="Script" id=1]
[ext_resource path="res://src/Palette/PaletteColor.gd" type="Script" id=2]
[sub_resource type="Resource" id=1]
script = ExtResource( 2 )
color = Color( 0.701961, 0.317647, 0.00784314, 1 )
index = 0
[sub_resource type="Resource" id=2]
script = ExtResource( 2 )
color = Color( 1, 0.6, 0.270588, 1 )
index = 1
[sub_resource type="Resource" id=3]
script = ExtResource( 2 )
color = Color( 1, 0.443137, 0, 1 )
index = 2
[sub_resource type="Resource" id=4]
script = ExtResource( 2 )
color = Color( 0, 0.6, 0.701961, 1 )
index = 3
[sub_resource type="Resource" id=5]
script = ExtResource( 2 )
color = Color( 0, 0.854902, 1, 1 )
index = 4
[sub_resource type="Resource" id=6]
script = ExtResource( 2 )
color = Color( 0.701961, 0.00784314, 0.00784314, 1 )
index = 5
[sub_resource type="Resource" id=7]
script = ExtResource( 2 )
color = Color( 1, 0.270588, 0.270588, 1 )
index = 6
[sub_resource type="Resource" id=8]
script = ExtResource( 2 )
color = Color( 1, 0.00784314, 0.00392157, 1 )
index = 7
[sub_resource type="Resource" id=9]
script = ExtResource( 2 )
color = Color( 0, 0.701961, 0.2, 1 )
index = 8
[sub_resource type="Resource" id=10]
script = ExtResource( 2 )
color = Color( 0, 1, 0.282353, 1 )
index = 9
[sub_resource type="Resource" id=11]
script = ExtResource( 2 )
color = Color( 0.501961, 0.00784314, 0.701961, 1 )
index = 10
[sub_resource type="Resource" id=12]
script = ExtResource( 2 )
color = Color( 0.792157, 0.270588, 1, 1 )
index = 11
[sub_resource type="Resource" id=13]
script = ExtResource( 2 )
color = Color( 0.705882, 0, 0.996078, 1 )
index = 12
[sub_resource type="Resource" id=14]
script = ExtResource( 2 )
color = Color( 0.498039, 0.701961, 0, 1 )
index = 13
[sub_resource type="Resource" id=15]
script = ExtResource( 2 )
color = Color( 0.709804, 1, 0, 1 )
index = 14
[sub_resource type="Resource" id=16]
script = ExtResource( 2 )
color = Color( 0.00784314, 0.0666667, 0.701961, 1 )
index = 15
[sub_resource type="Resource" id=17]
script = ExtResource( 2 )
color = Color( 0.270588, 0.329412, 1, 1 )
index = 16
[sub_resource type="Resource" id=18]
script = ExtResource( 2 )
color = Color( 0.00392157, 0.0862745, 1, 1 )
index = 17
[sub_resource type="Resource" id=19]
script = ExtResource( 2 )
color = Color( 0.701961, 0.54902, 0, 1 )
index = 18
[sub_resource type="Resource" id=20]
script = ExtResource( 2 )
color = Color( 1, 0.788235, 0, 1 )
index = 19
[sub_resource type="Resource" id=21]
script = ExtResource( 2 )
color = Color( 0.00784314, 0.619608, 0.701961, 1 )
index = 20
[sub_resource type="Resource" id=22]
script = ExtResource( 2 )
color = Color( 0.478431, 0.941176, 1, 1 )
index = 21
[sub_resource type="Resource" id=23]
script = ExtResource( 2 )
color = Color( 0, 0.882353, 1, 1 )
index = 22
[sub_resource type="Resource" id=24]
script = ExtResource( 2 )
color = Color( 0.701961, 0.301961, 0, 1 )
index = 23
[sub_resource type="Resource" id=25]
script = ExtResource( 2 )
color = Color( 1, 0.435294, 0, 1 )
index = 24
[resource]
resource_name = "Complementary"
script = ExtResource( 1 )
name = "Complementary"
comment = "Author: Erevoid"
width = 8
height = 4
colors = {
0: SubResource( 1 ),
1: SubResource( 2 ),
2: SubResource( 3 ),
3: SubResource( 4 ),
4: SubResource( 5 ),
5: SubResource( 6 ),
6: SubResource( 7 ),
7: SubResource( 8 ),
8: SubResource( 9 ),
9: SubResource( 10 ),
10: SubResource( 11 ),
11: SubResource( 12 ),
12: SubResource( 13 ),
13: SubResource( 14 ),
14: SubResource( 15 ),
15: SubResource( 16 ),
16: SubResource( 17 ),
17: SubResource( 18 ),
18: SubResource( 19 ),
19: SubResource( 20 ),
20: SubResource( 21 ),
21: SubResource( 22 ),
22: SubResource( 23 ),
23: SubResource( 24 ),
24: SubResource( 25 )
}
colors_max = 32

View file

@ -0,0 +1,135 @@
{
"colors": [
{
"color": "(0, 0, 0, 1)",
"index": 0
},
{
"color": "(0.1294, 0.1216, 0.2039, 1)",
"index": 1
},
{
"color": "(0.2667, 0.1569, 0.2314, 1)",
"index": 2
},
{
"color": "(0.4, 0.2196, 0.1922, 1)",
"index": 3
},
{
"color": "(0.5569, 0.3373, 0.2314, 1)",
"index": 4
},
{
"color": "(0.8745, 0.4392, 0.149, 1)",
"index": 5
},
{
"color": "(0.8471, 0.6275, 0.4, 1)",
"index": 6
},
{
"color": "(0.9294, 0.7647, 0.6039, 1)",
"index": 7
},
{
"color": "(0.9843, 0.949, 0.2118, 1)",
"index": 8
},
{
"color": "(0.6, 0.8941, 0.3137, 1)",
"index": 9
},
{
"color": "(0.4118, 0.7412, 0.1843, 1)",
"index": 10
},
{
"color": "(0.2118, 0.5765, 0.4314, 1)",
"index": 11
},
{
"color": "(0.2941, 0.4118, 0.1843, 1)",
"index": 12
},
{
"color": "(0.3216, 0.2941, 0.1373, 1)",
"index": 13
},
{
"color": "(0.1922, 0.2314, 0.2196, 1)",
"index": 14
},
{
"color": "(0.2471, 0.2471, 0.4549, 1)",
"index": 15
},
{
"color": "(0.1843, 0.3765, 0.5098, 1)",
"index": 16
},
{
"color": "(0.3569, 0.4314, 0.8824, 1)",
"index": 17
},
{
"color": "(0.3843, 0.6039, 1, 1)",
"index": 18
},
{
"color": "(0.3686, 0.8039, 0.8941, 1)",
"index": 19
},
{
"color": "(0.7922, 0.8588, 0.9843, 1)",
"index": 20
},
{
"color": "(1, 1, 1, 1)",
"index": 21
},
{
"color": "(0.6039, 0.6745, 0.7137, 1)",
"index": 22
},
{
"color": "(0.5137, 0.4941, 0.5294, 1)",
"index": 23
},
{
"color": "(0.4118, 0.4118, 0.4118, 1)",
"index": 24
},
{
"color": "(0.349, 0.3373, 0.3216, 1)",
"index": 25
},
{
"color": "(0.4588, 0.2588, 0.5373, 1)",
"index": 26
},
{
"color": "(0.6745, 0.1922, 0.1922, 1)",
"index": 27
},
{
"color": "(0.8471, 0.3373, 0.3843, 1)",
"index": 28
},
{
"color": "(0.8392, 0.4824, 0.7294, 1)",
"index": 29
},
{
"color": "(0.5569, 0.5922, 0.2863, 1)",
"index": 30
},
{
"color": "(0.5373, 0.4314, 0.1843, 1)",
"index": 31
}
],
"comment": "Author: DawnBringer\nFound in Lospec by CheetoHead/greusser\nhttps://lospec.com/palette-list/dawnbringer-32",
"height": 4,
"width": 8
}

View file

@ -1,209 +0,0 @@
[gd_resource type="Resource" load_steps=35 format=2]
[ext_resource path="res://src/Palette/PaletteColor.gd" type="Script" id=1]
[ext_resource path="res://src/Palette/Palette.gd" type="Script" id=2]
[sub_resource type="Resource" id=1]
script = ExtResource( 1 )
color = Color( 0, 0, 0, 1 )
index = 0
[sub_resource type="Resource" id=2]
script = ExtResource( 1 )
color = Color( 0.133333, 0.12549, 0.203922, 1 )
index = 1
[sub_resource type="Resource" id=3]
script = ExtResource( 1 )
color = Color( 0.270588, 0.156863, 0.235294, 1 )
index = 2
[sub_resource type="Resource" id=4]
script = ExtResource( 1 )
color = Color( 0.4, 0.223529, 0.192157, 1 )
index = 3
[sub_resource type="Resource" id=5]
script = ExtResource( 1 )
color = Color( 0.560784, 0.337255, 0.231373, 1 )
index = 4
[sub_resource type="Resource" id=6]
script = ExtResource( 1 )
color = Color( 0.87451, 0.443137, 0.14902, 1 )
index = 5
[sub_resource type="Resource" id=7]
script = ExtResource( 1 )
color = Color( 0.85098, 0.627451, 0.4, 1 )
index = 6
[sub_resource type="Resource" id=8]
script = ExtResource( 1 )
color = Color( 0.933333, 0.764706, 0.603922, 1 )
index = 7
[sub_resource type="Resource" id=9]
script = ExtResource( 1 )
color = Color( 0.984314, 0.94902, 0.211765, 1 )
index = 8
[sub_resource type="Resource" id=10]
script = ExtResource( 1 )
color = Color( 0.6, 0.898039, 0.313726, 1 )
index = 9
[sub_resource type="Resource" id=11]
script = ExtResource( 1 )
color = Color( 0.415686, 0.745098, 0.188235, 1 )
index = 10
[sub_resource type="Resource" id=12]
script = ExtResource( 1 )
color = Color( 0.215686, 0.580392, 0.431373, 1 )
index = 11
[sub_resource type="Resource" id=13]
script = ExtResource( 1 )
color = Color( 0.294118, 0.411765, 0.184314, 1 )
index = 12
[sub_resource type="Resource" id=14]
script = ExtResource( 1 )
color = Color( 0.321569, 0.294118, 0.141176, 1 )
index = 13
[sub_resource type="Resource" id=15]
script = ExtResource( 1 )
color = Color( 0.196078, 0.235294, 0.223529, 1 )
index = 14
[sub_resource type="Resource" id=16]
script = ExtResource( 1 )
color = Color( 0.247059, 0.247059, 0.454902, 1 )
index = 15
[sub_resource type="Resource" id=17]
script = ExtResource( 1 )
color = Color( 0.188235, 0.376471, 0.509804, 1 )
index = 16
[sub_resource type="Resource" id=18]
script = ExtResource( 1 )
color = Color( 0.356863, 0.431373, 0.882353, 1 )
index = 17
[sub_resource type="Resource" id=19]
script = ExtResource( 1 )
color = Color( 0.388235, 0.607843, 1, 1 )
index = 18
[sub_resource type="Resource" id=20]
script = ExtResource( 1 )
color = Color( 0.372549, 0.803922, 0.894118, 1 )
index = 19
[sub_resource type="Resource" id=21]
script = ExtResource( 1 )
color = Color( 0.796078, 0.858824, 0.988235, 1 )
index = 20
[sub_resource type="Resource" id=22]
script = ExtResource( 1 )
color = Color( 1, 1, 1, 1 )
index = 21
[sub_resource type="Resource" id=23]
script = ExtResource( 1 )
color = Color( 0.607843, 0.678431, 0.717647, 1 )
index = 22
[sub_resource type="Resource" id=24]
script = ExtResource( 1 )
color = Color( 0.517647, 0.494118, 0.529412, 1 )
index = 23
[sub_resource type="Resource" id=25]
script = ExtResource( 1 )
color = Color( 0.411765, 0.415686, 0.415686, 1 )
index = 24
[sub_resource type="Resource" id=26]
script = ExtResource( 1 )
color = Color( 0.34902, 0.337255, 0.321569, 1 )
index = 25
[sub_resource type="Resource" id=27]
script = ExtResource( 1 )
color = Color( 0.462745, 0.258824, 0.541176, 1 )
index = 26
[sub_resource type="Resource" id=28]
script = ExtResource( 1 )
color = Color( 0.67451, 0.196078, 0.196078, 1 )
index = 27
[sub_resource type="Resource" id=29]
script = ExtResource( 1 )
color = Color( 0.85098, 0.341176, 0.388235, 1 )
index = 28
[sub_resource type="Resource" id=30]
script = ExtResource( 1 )
color = Color( 0.843137, 0.482353, 0.729412, 1 )
index = 29
[sub_resource type="Resource" id=31]
script = ExtResource( 1 )
color = Color( 0.560784, 0.592157, 0.290196, 1 )
index = 30
[sub_resource type="Resource" id=32]
script = ExtResource( 1 )
color = Color( 0.541176, 0.435294, 0.188235, 1 )
index = 31
[resource]
resource_name = "Default"
script = ExtResource( 2 )
name = "Default"
comment = "Author: DawnBringer
Found in Lospec by CheetoHead/greusser
https://lospec.com/palette-list/dawnbringer-32"
width = 8
height = 4
colors = {
0: SubResource( 1 ),
1: SubResource( 2 ),
2: SubResource( 3 ),
3: SubResource( 4 ),
4: SubResource( 5 ),
5: SubResource( 6 ),
6: SubResource( 7 ),
7: SubResource( 8 ),
8: SubResource( 9 ),
9: SubResource( 10 ),
10: SubResource( 11 ),
11: SubResource( 12 ),
12: SubResource( 13 ),
13: SubResource( 14 ),
14: SubResource( 15 ),
15: SubResource( 16 ),
16: SubResource( 17 ),
17: SubResource( 18 ),
18: SubResource( 19 ),
19: SubResource( 20 ),
20: SubResource( 21 ),
21: SubResource( 22 ),
22: SubResource( 23 ),
23: SubResource( 24 ),
24: SubResource( 25 ),
25: SubResource( 26 ),
26: SubResource( 27 ),
27: SubResource( 28 ),
28: SubResource( 29 ),
29: SubResource( 30 ),
30: SubResource( 31 ),
31: SubResource( 32 )
}
colors_max = 32

View file

@ -0,0 +1,135 @@
{
"colors": [
{
"color": "(0.1922, 0.2, 0.2667, 1)",
"index": 0
},
{
"color": "(0.2863, 0.3059, 0.498, 1)",
"index": 1
},
{
"color": "(0.4431, 0.4667, 0.7137, 1)",
"index": 2
},
{
"color": "(0.5294, 0.549, 0.7569, 1)",
"index": 3
},
{
"color": "(0.2627, 0.3569, 0.3765, 1)",
"index": 4
},
{
"color": "(0.3647, 0.5176, 0.5569, 1)",
"index": 5
},
{
"color": "(0.5059, 0.7529, 0.8118, 1)",
"index": 6
},
{
"color": "(0.6118, 0.7961, 0.8392, 1)",
"index": 7
},
{
"color": "(0.3137, 0.3843, 0.2941, 1)",
"index": 8
},
{
"color": "(0.3569, 0.549, 0.302, 1)",
"index": 9
},
{
"color": "(0.549, 0.7451, 0.4863, 1)",
"index": 10
},
{
"color": "(0.651, 0.8706, 0.5843, 1)",
"index": 11
},
{
"color": "(0.298, 0.1686, 0.1569, 1)",
"index": 12
},
{
"color": "(0.502, 0.3412, 0.3255, 1)",
"index": 13
},
{
"color": "(0.6627, 0.4235, 0.4039, 1)",
"index": 14
},
{
"color": "(0.7882, 0.6627, 0.651, 1)",
"index": 15
},
{
"color": "(0.2471, 0.1725, 0.1686, 1)",
"index": 16
},
{
"color": "(0.4941, 0.3765, 0.2588, 1)",
"index": 17
},
{
"color": "(0.5137, 0.4275, 0.3412, 1)",
"index": 18
},
{
"color": "(0.7882, 0.6314, 0.4784, 1)",
"index": 19
},
{
"color": "(0.3725, 0.3686, 0.2667, 1)",
"index": 20
},
{
"color": "(0.5765, 0.5686, 0.4196, 1)",
"index": 21
},
{
"color": "(0.7843, 0.7725, 0.5961, 1)",
"index": 22
},
{
"color": "(0.9255, 0.9137, 0.7255, 1)",
"index": 23
},
{
"color": "(0.2118, 0.1686, 0.2157, 1)",
"index": 24
},
{
"color": "(0.3529, 0.2353, 0.3608, 1)",
"index": 25
},
{
"color": "(0.4745, 0.3294, 0.4863, 1)",
"index": 26
},
{
"color": "(0.6745, 0.4353, 0.6902, 1)",
"index": 27
},
{
"color": "(0.1255, 0.1216, 0.1216, 1)",
"index": 28
},
{
"color": "(0.1765, 0.1765, 0.1765, 1)",
"index": 29
},
{
"color": "(0.4314, 0.4314, 0.4314, 1)",
"index": 30
},
{
"color": "(0.6667, 0.6667, 0.6667, 1)",
"index": 31
}
],
"comment": "Author: Erevoid",
"height": 4,
"width": 8
}

View file

@ -1,207 +0,0 @@
[gd_resource type="Resource" load_steps=35 format=2]
[ext_resource path="res://src/Palette/PaletteColor.gd" type="Script" id=1]
[ext_resource path="res://src/Palette/Palette.gd" type="Script" id=2]
[sub_resource type="Resource" id=4]
script = ExtResource( 1 )
color = Color( 0.195831, 0.201393, 0.269531, 1 )
index = 0
[sub_resource type="Resource" id=1]
script = ExtResource( 1 )
color = Color( 0.29, 0.3075, 0.5, 1 )
index = 1
[sub_resource type="Resource" id=5]
script = ExtResource( 1 )
color = Color( 0.446777, 0.469116, 0.714844, 1 )
index = 2
[sub_resource type="Resource" id=3]
script = ExtResource( 1 )
color = Color( 0.532837, 0.551585, 0.757813, 1 )
index = 3
[sub_resource type="Resource" id=6]
script = ExtResource( 1 )
color = Color( 0.263458, 0.357527, 0.378906, 1 )
index = 4
[sub_resource type="Resource" id=9]
script = ExtResource( 1 )
color = Color( 0.366577, 0.52082, 0.558594, 1 )
index = 5
[sub_resource type="Resource" id=8]
script = ExtResource( 1 )
color = Color( 0.507813, 0.75586, 0.8125, 1 )
index = 6
[sub_resource type="Resource" id=10]
script = ExtResource( 1 )
color = Color( 0.61348, 0.797857, 0.839844, 1 )
index = 7
[sub_resource type="Resource" id=11]
script = ExtResource( 1 )
color = Color( 0.316449, 0.386719, 0.296082, 1 )
index = 8
[sub_resource type="Resource" id=14]
script = ExtResource( 1 )
color = Color( 0.360175, 0.550781, 0.30336, 1 )
index = 9
[sub_resource type="Resource" id=15]
script = ExtResource( 1 )
color = Color( 0.549189, 0.746094, 0.48671, 1 )
index = 10
[sub_resource type="Resource" id=13]
script = ExtResource( 1 )
color = Color( 0.652127, 0.871094, 0.585266, 1 )
index = 11
[sub_resource type="Resource" id=29]
script = ExtResource( 1 )
color = Color( 0.300781, 0.170901, 0.158615, 1 )
index = 12
[sub_resource type="Resource" id=30]
script = ExtResource( 1 )
color = Color( 0.503906, 0.341829, 0.326752, 1 )
index = 13
[sub_resource type="Resource" id=27]
script = ExtResource( 1 )
color = Color( 0.664063, 0.425966, 0.404663, 1 )
index = 14
[sub_resource type="Resource" id=28]
script = ExtResource( 1 )
color = Color( 0.789063, 0.66438, 0.653442, 1 )
index = 15
[sub_resource type="Resource" id=26]
script = ExtResource( 1 )
color = Color( 0.25, 0.175261, 0.168945, 1 )
index = 16
[sub_resource type="Resource" id=21]
script = ExtResource( 1 )
color = Color( 0.496094, 0.378853, 0.261612, 1 )
index = 17
[sub_resource type="Resource" id=24]
script = ExtResource( 1 )
color = Color( 0.515625, 0.429016, 0.342407, 1 )
index = 18
[sub_resource type="Resource" id=25]
script = ExtResource( 1 )
color = Color( 0.789063, 0.633157, 0.480835, 1 )
index = 19
[sub_resource type="Resource" id=19]
script = ExtResource( 1 )
color = Color( 0.375, 0.369586, 0.268066, 1 )
index = 20
[sub_resource type="Resource" id=20]
script = ExtResource( 1 )
color = Color( 0.578125, 0.569414, 0.422302, 1 )
index = 21
[sub_resource type="Resource" id=18]
script = ExtResource( 1 )
color = Color( 0.785156, 0.775848, 0.598068, 1 )
index = 22
[sub_resource type="Resource" id=17]
script = ExtResource( 1 )
color = Color( 0.925781, 0.916637, 0.726883, 1 )
index = 23
[sub_resource type="Resource" id=34]
script = ExtResource( 1 )
color = Color( 0.215531, 0.171753, 0.21875, 1 )
index = 24
[sub_resource type="Resource" id=31]
script = ExtResource( 1 )
color = Color( 0.35426, 0.236984, 0.363281, 1 )
index = 25
[sub_resource type="Resource" id=35]
script = ExtResource( 1 )
color = Color( 0.47823, 0.329971, 0.488281, 1 )
index = 26
[sub_resource type="Resource" id=33]
script = ExtResource( 1 )
color = Color( 0.674684, 0.437531, 0.691406, 1 )
index = 27
[sub_resource type="Resource" id=36]
script = ExtResource( 1 )
color = Color( 0.128906, 0.122864, 0.122864, 1 )
index = 28
[sub_resource type="Resource" id=39]
script = ExtResource( 1 )
color = Color( 0.176471, 0.176471, 0.176471, 1 )
index = 29
[sub_resource type="Resource" id=38]
script = ExtResource( 1 )
color = Color( 0.431373, 0.431373, 0.431373, 1 )
index = 30
[sub_resource type="Resource" id=37]
script = ExtResource( 1 )
color = Color( 0.670588, 0.670588, 0.670588, 1 )
index = 31
[resource]
resource_name = "Monochromatic"
script = ExtResource( 2 )
name = "Monochromatic"
comment = "Author: Erevoid"
width = 8
height = 4
colors = {
0: SubResource( 4 ),
1: SubResource( 1 ),
2: SubResource( 5 ),
3: SubResource( 3 ),
4: SubResource( 6 ),
5: SubResource( 9 ),
6: SubResource( 8 ),
7: SubResource( 10 ),
8: SubResource( 11 ),
9: SubResource( 14 ),
10: SubResource( 15 ),
11: SubResource( 13 ),
12: SubResource( 29 ),
13: SubResource( 30 ),
14: SubResource( 27 ),
15: SubResource( 28 ),
16: SubResource( 26 ),
17: SubResource( 21 ),
18: SubResource( 24 ),
19: SubResource( 25 ),
20: SubResource( 19 ),
21: SubResource( 20 ),
22: SubResource( 18 ),
23: SubResource( 17 ),
24: SubResource( 34 ),
25: SubResource( 31 ),
26: SubResource( 35 ),
27: SubResource( 33 ),
28: SubResource( 36 ),
29: SubResource( 39 ),
30: SubResource( 38 ),
31: SubResource( 37 )
}
colors_max = 32

View file

@ -0,0 +1,147 @@
{
"colors": [
{
"color": "(0.7569, 0.3294, 0, 1)",
"index": 0
},
{
"color": "(0.502, 0.2196, 0, 1)",
"index": 1
},
{
"color": "(1, 0.4471, 0, 1)",
"index": 2
},
{
"color": "(0.2471, 0.1098, 0, 1)",
"index": 3
},
{
"color": "(0.902, 0.4039, 0, 1)",
"index": 4
},
{
"color": "(0.7569, 0, 0, 1)",
"index": 5
},
{
"color": "(0.502, 0, 0, 1)",
"index": 6
},
{
"color": "(1, 0, 0, 1)",
"index": 7
},
{
"color": "(0.2471, 0, 0, 1)",
"index": 8
},
{
"color": "(0.902, 0.0039, 0.0039, 1)",
"index": 9
},
{
"color": "(0.5294, 0, 0.7569, 1)",
"index": 10
},
{
"color": "(0.349, 0, 0.502, 1)",
"index": 11
},
{
"color": "(0.702, 0, 1, 1)",
"index": 12
},
{
"color": "(0.1765, 0, 0.2471, 1)",
"index": 13
},
{
"color": "(0.6314, 0, 0.8941, 1)",
"index": 14
},
{
"color": "(0, 0.0627, 0.7569, 1)",
"index": 15
},
{
"color": "(0, 0.0431, 0.502, 1)",
"index": 16
},
{
"color": "(0, 0.0784, 1, 1)",
"index": 17
},
{
"color": "(0, 0.0157, 0.2471, 1)",
"index": 18
},
{
"color": "(0.0039, 0.0784, 0.902, 1)",
"index": 19
},
{
"color": "(0, 0.6667, 0.7569, 1)",
"index": 20
},
{
"color": "(0, 0.4392, 0.502, 1)",
"index": 21
},
{
"color": "(0, 0.8824, 1, 1)",
"index": 22
},
{
"color": "(0, 0.2196, 0.2471, 1)",
"index": 23
},
{
"color": "(0, 0.7922, 0.902, 1)",
"index": 24
},
{
"color": "(0, 0.7569, 0.2118, 1)",
"index": 25
},
{
"color": "(0, 0.502, 0.1373, 1)",
"index": 26
},
{
"color": "(0, 1, 0.2824, 1)",
"index": 27
},
{
"color": "(0, 0.2471, 0.0667, 1)",
"index": 28
},
{
"color": "(0, 0.902, 0.2549, 1)",
"index": 29
},
{
"color": "(0.7216, 0.7569, 0, 1)",
"index": 30
},
{
"color": "(0.4745, 0.502, 0, 1)",
"index": 31
},
{
"color": "(0.949, 1, 0, 1)",
"index": 32
},
{
"color": "(0.2392, 0.2471, 0, 1)",
"index": 33
},
{
"color": "(0.8588, 0.902, 0, 1)",
"index": 34
}
],
"comment": "Author: Erevoid",
"height": 5,
"width": 8
}

View file

@ -1,225 +0,0 @@
[gd_resource type="Resource" load_steps=38 format=2]
[ext_resource path="res://src/Palette/Palette.gd" type="Script" id=1]
[ext_resource path="res://src/Palette/PaletteColor.gd" type="Script" id=2]
[sub_resource type="Resource" id=1]
script = ExtResource( 2 )
color = Color( 0.760784, 0.329412, 0, 1 )
index = 0
[sub_resource type="Resource" id=2]
script = ExtResource( 2 )
color = Color( 0.501961, 0.223529, 0, 1 )
index = 1
[sub_resource type="Resource" id=3]
script = ExtResource( 2 )
color = Color( 1, 0.45098, 0, 1 )
index = 2
[sub_resource type="Resource" id=4]
script = ExtResource( 2 )
color = Color( 0.25098, 0.113725, 0, 1 )
index = 3
[sub_resource type="Resource" id=5]
script = ExtResource( 2 )
color = Color( 0.901961, 0.403922, 0, 1 )
index = 4
[sub_resource type="Resource" id=6]
script = ExtResource( 2 )
color = Color( 0.760784, 0, 0, 1 )
index = 5
[sub_resource type="Resource" id=7]
script = ExtResource( 2 )
color = Color( 0.501961, 0, 0, 1 )
index = 6
[sub_resource type="Resource" id=8]
script = ExtResource( 2 )
color = Color( 1, 0, 0, 1 )
index = 7
[sub_resource type="Resource" id=9]
script = ExtResource( 2 )
color = Color( 0.25098, 0, 0, 1 )
index = 8
[sub_resource type="Resource" id=10]
script = ExtResource( 2 )
color = Color( 0.901961, 0.00392157, 0.00392157, 1 )
index = 9
[sub_resource type="Resource" id=11]
script = ExtResource( 2 )
color = Color( 0.533333, 0, 0.760784, 1 )
index = 10
[sub_resource type="Resource" id=12]
script = ExtResource( 2 )
color = Color( 0.34902, 0, 0.501961, 1 )
index = 11
[sub_resource type="Resource" id=13]
script = ExtResource( 2 )
color = Color( 0.701961, 0, 1, 1 )
index = 12
[sub_resource type="Resource" id=14]
script = ExtResource( 2 )
color = Color( 0.176471, 0, 0.25098, 1 )
index = 13
[sub_resource type="Resource" id=15]
script = ExtResource( 2 )
color = Color( 0.635294, 0, 0.898039, 1 )
index = 14
[sub_resource type="Resource" id=16]
script = ExtResource( 2 )
color = Color( 0, 0.0627451, 0.760784, 1 )
index = 15
[sub_resource type="Resource" id=17]
script = ExtResource( 2 )
color = Color( 0, 0.0431373, 0.501961, 1 )
index = 16
[sub_resource type="Resource" id=18]
script = ExtResource( 2 )
color = Color( 0, 0.0823529, 1, 1 )
index = 17
[sub_resource type="Resource" id=19]
script = ExtResource( 2 )
color = Color( 0, 0.0196078, 0.25098, 1 )
index = 18
[sub_resource type="Resource" id=20]
script = ExtResource( 2 )
color = Color( 0.00392157, 0.0784314, 0.901961, 1 )
index = 19
[sub_resource type="Resource" id=21]
script = ExtResource( 2 )
color = Color( 0, 0.670588, 0.760784, 1 )
index = 20
[sub_resource type="Resource" id=22]
script = ExtResource( 2 )
color = Color( 0, 0.443137, 0.501961, 1 )
index = 21
[sub_resource type="Resource" id=23]
script = ExtResource( 2 )
color = Color( 0, 0.882353, 1, 1 )
index = 22
[sub_resource type="Resource" id=24]
script = ExtResource( 2 )
color = Color( 0, 0.219608, 0.25098, 1 )
index = 23
[sub_resource type="Resource" id=25]
script = ExtResource( 2 )
color = Color( 0, 0.796078, 0.901961, 1 )
index = 24
[sub_resource type="Resource" id=26]
script = ExtResource( 2 )
color = Color( 0, 0.760784, 0.215686, 1 )
index = 25
[sub_resource type="Resource" id=27]
script = ExtResource( 2 )
color = Color( 0, 0.501961, 0.141176, 1 )
index = 26
[sub_resource type="Resource" id=28]
script = ExtResource( 2 )
color = Color( 0, 1, 0.282353, 1 )
index = 27
[sub_resource type="Resource" id=29]
script = ExtResource( 2 )
color = Color( 0, 0.25098, 0.0705882, 1 )
index = 28
[sub_resource type="Resource" id=30]
script = ExtResource( 2 )
color = Color( 0, 0.901961, 0.254902, 1 )
index = 29
[sub_resource type="Resource" id=31]
script = ExtResource( 2 )
color = Color( 0.721569, 0.760784, 0, 1 )
index = 30
[sub_resource type="Resource" id=32]
script = ExtResource( 2 )
color = Color( 0.47451, 0.501961, 0, 1 )
index = 31
[sub_resource type="Resource" id=33]
script = ExtResource( 2 )
color = Color( 0.94902, 1, 0, 1 )
index = 32
[sub_resource type="Resource" id=34]
script = ExtResource( 2 )
color = Color( 0.239216, 0.25098, 0, 1 )
index = 33
[sub_resource type="Resource" id=35]
script = ExtResource( 2 )
color = Color( 0.862745, 0.901961, 0, 1 )
index = 34
[resource]
resource_name = "Shades"
script = ExtResource( 1 )
name = "Shades"
comment = "Author: Erevoid"
width = 8
height = 5
colors = {
0: SubResource( 1 ),
1: SubResource( 2 ),
2: SubResource( 3 ),
3: SubResource( 4 ),
4: SubResource( 5 ),
5: SubResource( 6 ),
6: SubResource( 7 ),
7: SubResource( 8 ),
8: SubResource( 9 ),
9: SubResource( 10 ),
10: SubResource( 11 ),
11: SubResource( 12 ),
12: SubResource( 13 ),
13: SubResource( 14 ),
14: SubResource( 15 ),
15: SubResource( 16 ),
16: SubResource( 17 ),
17: SubResource( 18 ),
18: SubResource( 19 ),
19: SubResource( 20 ),
20: SubResource( 21 ),
21: SubResource( 22 ),
22: SubResource( 23 ),
23: SubResource( 24 ),
24: SubResource( 25 ),
25: SubResource( 26 ),
26: SubResource( 27 ),
27: SubResource( 28 ),
28: SubResource( 29 ),
29: SubResource( 30 ),
30: SubResource( 31 ),
31: SubResource( 32 ),
32: SubResource( 33 ),
33: SubResource( 34 ),
34: SubResource( 35 )
}
colors_max = 40

View file

@ -0,0 +1,107 @@
{
"colors": [
{
"color": "(0.5216, 0.1686, 0.1922, 1)",
"index": 0
},
{
"color": "(0.8, 0.3922, 0.4196, 1)",
"index": 1
},
{
"color": "(0.8863, 0.8745, 0.4, 1)",
"index": 2
},
{
"color": "(0.2314, 0.4667, 0.6, 1)",
"index": 3
},
{
"color": "(0.2196, 0.4, 0.502, 1)",
"index": 4
},
{
"color": "(0.0784, 0.102, 0.5216, 1)",
"index": 5
},
{
"color": "(0.2039, 0.2314, 0.8196, 1)",
"index": 6
},
{
"color": "(0.902, 0.4118, 0.1843, 1)",
"index": 7
},
{
"color": "(0.2471, 0.6196, 0.0902, 1)",
"index": 8
},
{
"color": "(0.2275, 0.5216, 0.102, 1)",
"index": 9
},
{
"color": "(0.5373, 0.0157, 0, 1)",
"index": 10
},
{
"color": "(0.8196, 0.0196, 0, 1)",
"index": 11
},
{
"color": "(0.8667, 0.902, 0.0314, 1)",
"index": 12
},
{
"color": "(0.0627, 0.3686, 0.6196, 1)",
"index": 13
},
{
"color": "(0.0275, 0.2941, 0.5216, 1)",
"index": 14
},
{
"color": "(0.5137, 0.0824, 0.5373, 1)",
"index": 15
},
{
"color": "(0.7843, 0.2588, 0.8196, 1)",
"index": 16
},
{
"color": "(0.902, 0.749, 0.2471, 1)",
"index": 17
},
{
"color": "(0.1373, 0.6196, 0.5216, 1)",
"index": 18
},
{
"color": "(0.1373, 0.5216, 0.4392, 1)",
"index": 19
},
{
"color": "(0.1137, 0.5373, 0.102, 1)",
"index": 20
},
{
"color": "(0.3098, 0.8196, 0.2863, 1)",
"index": 21
},
{
"color": "(0.3765, 0.2745, 0.902, 1)",
"index": 22
},
{
"color": "(0.6196, 0.349, 0.1569, 1)",
"index": 23
},
{
"color": "(0.5216, 0.3098, 0.1569, 1)",
"index": 24
}
],
"comment": "Author: Erevoid",
"height": 4,
"width": 8
}

View file

@ -1,165 +0,0 @@
[gd_resource type="Resource" load_steps=28 format=2]
[ext_resource path="res://src/Palette/Palette.gd" type="Script" id=1]
[ext_resource path="res://src/Palette/PaletteColor.gd" type="Script" id=2]
[sub_resource type="Resource" id=1]
script = ExtResource( 2 )
color = Color( 0.521569, 0.172549, 0.196078, 1 )
index = 0
[sub_resource type="Resource" id=2]
script = ExtResource( 2 )
color = Color( 0.8, 0.392157, 0.419608, 1 )
index = 1
[sub_resource type="Resource" id=3]
script = ExtResource( 2 )
color = Color( 0.890196, 0.87451, 0.4, 1 )
index = 2
[sub_resource type="Resource" id=4]
script = ExtResource( 2 )
color = Color( 0.235294, 0.470588, 0.6, 1 )
index = 3
[sub_resource type="Resource" id=5]
script = ExtResource( 2 )
color = Color( 0.219608, 0.4, 0.501961, 1 )
index = 4
[sub_resource type="Resource" id=6]
script = ExtResource( 2 )
color = Color( 0.0784314, 0.101961, 0.521569, 1 )
index = 5
[sub_resource type="Resource" id=7]
script = ExtResource( 2 )
color = Color( 0.207843, 0.235294, 0.819608, 1 )
index = 6
[sub_resource type="Resource" id=8]
script = ExtResource( 2 )
color = Color( 0.901961, 0.411765, 0.188235, 1 )
index = 7
[sub_resource type="Resource" id=9]
script = ExtResource( 2 )
color = Color( 0.25098, 0.619608, 0.0941176, 1 )
index = 8
[sub_resource type="Resource" id=10]
script = ExtResource( 2 )
color = Color( 0.227451, 0.521569, 0.105882, 1 )
index = 9
[sub_resource type="Resource" id=11]
script = ExtResource( 2 )
color = Color( 0.541176, 0.0196078, 0, 1 )
index = 10
[sub_resource type="Resource" id=12]
script = ExtResource( 2 )
color = Color( 0.819608, 0.0235294, 0, 1 )
index = 11
[sub_resource type="Resource" id=13]
script = ExtResource( 2 )
color = Color( 0.870588, 0.901961, 0.0352941, 1 )
index = 12
[sub_resource type="Resource" id=14]
script = ExtResource( 2 )
color = Color( 0.0627451, 0.372549, 0.619608, 1 )
index = 13
[sub_resource type="Resource" id=15]
script = ExtResource( 2 )
color = Color( 0.027451, 0.298039, 0.521569, 1 )
index = 14
[sub_resource type="Resource" id=16]
script = ExtResource( 2 )
color = Color( 0.517647, 0.0862745, 0.541176, 1 )
index = 15
[sub_resource type="Resource" id=17]
script = ExtResource( 2 )
color = Color( 0.788235, 0.258824, 0.819608, 1 )
index = 16
[sub_resource type="Resource" id=18]
script = ExtResource( 2 )
color = Color( 0.901961, 0.74902, 0.25098, 1 )
index = 17
[sub_resource type="Resource" id=19]
script = ExtResource( 2 )
color = Color( 0.137255, 0.619608, 0.521569, 1 )
index = 18
[sub_resource type="Resource" id=20]
script = ExtResource( 2 )
color = Color( 0.141176, 0.521569, 0.443137, 1 )
index = 19
[sub_resource type="Resource" id=21]
script = ExtResource( 2 )
color = Color( 0.117647, 0.541176, 0.101961, 1 )
index = 20
[sub_resource type="Resource" id=22]
script = ExtResource( 2 )
color = Color( 0.309804, 0.819608, 0.290196, 1 )
index = 21
[sub_resource type="Resource" id=23]
script = ExtResource( 2 )
color = Color( 0.376471, 0.278431, 0.901961, 1 )
index = 22
[sub_resource type="Resource" id=24]
script = ExtResource( 2 )
color = Color( 0.619608, 0.352941, 0.156863, 1 )
index = 23
[sub_resource type="Resource" id=25]
script = ExtResource( 2 )
color = Color( 0.521569, 0.309804, 0.156863, 1 )
index = 24
[resource]
resource_name = "Triad"
script = ExtResource( 1 )
name = "Triad"
comment = "Author: Erevoid"
width = 8
height = 4
colors = {
0: SubResource( 1 ),
1: SubResource( 2 ),
2: SubResource( 3 ),
3: SubResource( 4 ),
4: SubResource( 5 ),
5: SubResource( 6 ),
6: SubResource( 7 ),
7: SubResource( 8 ),
8: SubResource( 9 ),
9: SubResource( 10 ),
10: SubResource( 11 ),
11: SubResource( 12 ),
12: SubResource( 13 ),
13: SubResource( 14 ),
14: SubResource( 15 ),
15: SubResource( 16 ),
16: SubResource( 17 ),
17: SubResource( 18 ),
18: SubResource( 19 ),
19: SubResource( 20 ),
20: SubResource( 21 ),
21: SubResource( 22 ),
22: SubResource( 23 ),
23: SubResource( 24 ),
24: SubResource( 25 )
}
colors_max = 32

View file

@ -463,11 +463,8 @@ var cel_button_scene: PackedScene = load("res://src/UI/Timeline/CelButton.tscn")
## Transparent checker of the main canvas. It has the [param TransparentChecker.gd] script attached. ## Transparent checker of the main canvas. It has the [param TransparentChecker.gd] script attached.
@onready var transparent_checker: ColorRect = control.find_child("TransparentChecker") @onready var transparent_checker: ColorRect = control.find_child("TransparentChecker")
## The palettes panel. It has the [param PalettePanel.gd] script attached. ## The perspective editor. It has the [param PerspectiveEditor.gd] script attached.
@onready var palette_panel: PalettePanel = control.find_child("Palettes")
## The perspectice editor. It has the [param PerspectiveEditor.gd] script attached.
@onready var perspective_editor := control.find_child("Perspective Editor") @onready var perspective_editor := control.find_child("Perspective Editor")
## The top menu container. It has the [param TopMenuContainer.gd] script attached. ## The top menu container. It has the [param TopMenuContainer.gd] script attached.
@onready var top_menu_container: Panel = control.find_child("TopMenuContainer") @onready var top_menu_container: Panel = control.find_child("TopMenuContainer")
## The label indicating cursor position. ## The label indicating cursor position.

View file

@ -32,19 +32,12 @@ func handle_loading_file(file: String) -> void:
open_pxo_file(file) open_pxo_file(file)
elif file_ext == "tres": # Godot resource file elif file_ext == "tres": # Godot resource file
var resource := load(file) return
if resource is Palette:
Palettes.import_palette(resource, file.get_file())
else:
var file_name: String = file.get_file()
Global.error_dialog.set_text(tr("Can't load file '%s'.") % [file_name])
Global.error_dialog.popup_centered()
Global.dialog_open(true)
elif file_ext == "tscn": # Godot scene file elif file_ext == "tscn": # Godot scene file
return return
elif file_ext == "gpl" or file_ext == "pal" or file_ext == "json": elif file_ext == "gpl" or file_ext == "pal" or file_ext == "json":
Palettes.import_palette_from_path(file) Palettes.import_palette_from_path(file, true)
elif file_ext in ["pck", "zip"]: # Godot resource pack file elif file_ext in ["pck", "zip"]: # Godot resource pack file
Global.preferences_dialog.extensions.install_extension(file) Global.preferences_dialog.extensions.install_extension(file)

View file

@ -1,19 +1,19 @@
# gdlint: ignore=max-public-methods
extends Node extends Node
# Presets for creating a new palette signal palette_selected(palette_name: String)
signal new_palette_imported
## Presets for creating a new palette
enum NewPalettePresetType { enum NewPalettePresetType {
EMPTY = 0, FROM_CURRENT_PALETTE = 1, FROM_CURRENT_SPRITE = 2, FROM_CURRENT_SELECTION = 3 EMPTY = 0, FROM_CURRENT_PALETTE = 1, FROM_CURRENT_SPRITE = 2, FROM_CURRENT_SELECTION = 3
} }
## Color options when user creates a new palette from current sprite or selection
# Color options when user creates a new palette from current sprite or selection
enum GetColorsFrom { CURRENT_FRAME = 0, CURRENT_CEL = 1, ALL_FRAMES = 2 } enum GetColorsFrom { CURRENT_FRAME = 0, CURRENT_CEL = 1, ALL_FRAMES = 2 }
const DEFAULT_PALETTE_NAME := "Default" const DEFAULT_PALETTE_NAME := "Default"
var palettes_write_path := Global.home_data_directory.path_join("Palettes") var palettes_write_path := Global.home_data_directory.path_join("Palettes")
# All available palettes ## All available palettes
var palettes := {} var palettes := {}
# Currently displayed palette ## Currently displayed palette
var current_palette: Palette = null var current_palette: Palette = null
# Indexes of colors that are selected in palette # Indexes of colors that are selected in palette
@ -26,66 +26,48 @@ func _ready() -> void:
_load_palettes() _load_palettes()
func get_palettes() -> Dictionary:
return palettes
func get_current_palette() -> Palette:
return current_palette
func does_palette_exist(palette_name: String) -> bool: func does_palette_exist(palette_name: String) -> bool:
for palette_path in palettes.keys(): for name_to_test: String in palettes.keys():
var file_name = palette_path.get_basename().get_file() if name_to_test == palette_name:
var stripped_palette_name = Palette.strip_unvalid_characters(palette_name)
if file_name == stripped_palette_name:
return true return true
return false return false
func select_palette(palette_path: String) -> void: func select_palette(palette_name: String) -> void:
current_palette = palettes.get(palette_path) current_palette = palettes.get(palette_name)
_clear_selected_colors() _clear_selected_colors()
Global.config_cache.set_value("data", "last_palette", current_palette.name) Global.config_cache.set_value("data", "last_palette", current_palette.name)
palette_selected.emit(palette_name)
func is_any_palette_selected() -> bool: func is_any_palette_selected() -> bool:
if self.current_palette: if is_instance_valid(current_palette):
return true return true
return false return false
func _current_palette_save() -> String:
var save_path := ""
if current_palette:
save_path = _save_palette(self.current_palette)
return save_path
func _ensure_palette_directory_exists() -> void: func _ensure_palette_directory_exists() -> void:
var dir := DirAccess.open(Global.home_data_directory) var dir := DirAccess.open(Global.home_data_directory)
if is_instance_valid(dir) and not dir.dir_exists(palettes_write_path): if is_instance_valid(dir) and not dir.dir_exists(palettes_write_path):
dir.make_dir(palettes_write_path) dir.make_dir(palettes_write_path)
func _save_palette(palette: Palette) -> String: func _save_palette(palette: Palette = current_palette) -> void:
_ensure_palette_directory_exists() _ensure_palette_directory_exists()
# Save old resource name and set new resource name if not is_instance_valid(palette):
var old_resource_name := palette.resource_name return
palette.set_resource_name(palette.name) var old_name := palette.path.get_basename().get_file()
# If the palette's name has changed, remove the old palette file
# If resource name changed remove the old palette file if old_name != palette.name:
if old_resource_name != palette.resource_name: DirAccess.remove_absolute(palette.path)
var old_palette := palettes_write_path.path_join(old_resource_name) + ".tres" palettes.erase(old_name)
_delete_palette(old_palette)
# Save palette # Save palette
var save_path := palettes_write_path.path_join(palette.resource_name) + ".tres" var save_path := palettes_write_path.path_join(palette.name) + ".json"
palette.resource_path = save_path palette.path = save_path
var err := ResourceSaver.save(palette, save_path) var err := palette.save_to_file()
if err != OK: if err != OK:
Global.notification_label("Failed to save palette") Global.notification_label("Failed to save palette")
return save_path
func create_new_palette( func create_new_palette(
@ -116,22 +98,22 @@ func create_new_palette(
func _create_new_empty_palette( func _create_new_empty_palette(
palette_name: String, comment: String, width: int, height: int palette_name: String, comment: String, width: int, height: int
) -> void: ) -> void:
var new_palette: Palette = Palette.new(palette_name, width, height, comment) var new_palette := Palette.new(palette_name, width, height, comment)
var palette_path := _save_palette(new_palette) _save_palette(new_palette)
palettes[palette_path] = new_palette palettes[palette_name] = new_palette
select_palette(palette_path) select_palette(palette_name)
func _create_new_palette_from_current_palette(palette_name: String, comment: String) -> void: func _create_new_palette_from_current_palette(palette_name: String, comment: String) -> void:
if !current_palette: if !current_palette:
return return
var new_palette := current_palette.duplicate() as Palette var new_palette := current_palette.duplicate()
new_palette.name = palette_name new_palette.name = palette_name
new_palette.comment = comment new_palette.comment = comment
new_palette.set_resource_name(palette_name) new_palette.path = palettes_write_path.path_join(new_palette.name) + ".json"
var palette_path := _save_palette(new_palette) _save_palette(new_palette)
palettes[palette_path] = new_palette palettes[palette_name] = new_palette
select_palette(palette_path) select_palette(palette_name)
func _create_new_palette_from_current_selection( func _create_new_palette_from_current_selection(
@ -141,7 +123,7 @@ func _create_new_palette_from_current_selection(
height: int, height: int,
add_alpha_colors: bool, add_alpha_colors: bool,
get_colors_from: int get_colors_from: int
): ) -> void:
var new_palette := Palette.new(palette_name, width, height, comment) var new_palette := Palette.new(palette_name, width, height, comment)
var current_project := Global.current_project var current_project := Global.current_project
var pixels: Array[Vector2i] = [] var pixels: Array[Vector2i] = []
@ -160,7 +142,7 @@ func _create_new_palette_from_current_sprite(
height: int, height: int,
add_alpha_colors: bool, add_alpha_colors: bool,
get_colors_from: int get_colors_from: int
): ) -> void:
var new_palette := Palette.new(palette_name, width, height, comment) var new_palette := Palette.new(palette_name, width, height, comment)
var current_project := Global.current_project var current_project := Global.current_project
var pixels: Array[Vector2i] = [] var pixels: Array[Vector2i] = []
@ -170,9 +152,11 @@ func _create_new_palette_from_current_sprite(
_fill_new_palette_with_colors(pixels, new_palette, add_alpha_colors, get_colors_from) _fill_new_palette_with_colors(pixels, new_palette, add_alpha_colors, get_colors_from)
## Fills [param new_palette] with the colors of the [param pixels] of the current sprite.
## Used when creating a new palette from the UI.
func _fill_new_palette_with_colors( func _fill_new_palette_with_colors(
pixels: Array[Vector2i], new_palette: Palette, add_alpha_colors: bool, get_colors_from: int pixels: Array[Vector2i], new_palette: Palette, add_alpha_colors: bool, get_colors_from: int
): ) -> void:
var current_project := Global.current_project var current_project := Global.current_project
var cels: Array[BaseCel] = [] var cels: Array[BaseCel] = []
match get_colors_from: match get_colors_from:
@ -201,28 +185,29 @@ func _fill_new_palette_with_colors(
if not new_palette.has_theme_color(color): if not new_palette.has_theme_color(color):
new_palette.add_color(color) new_palette.add_color(color)
var palette_path := _save_palette(new_palette) _save_palette(new_palette)
palettes[palette_path] = new_palette palettes[new_palette.name] = new_palette
select_palette(palette_path) select_palette(new_palette.name)
func current_palette_edit(palette_name: String, comment: String, width: int, height: int) -> void: func current_palette_edit(palette_name: String, comment: String, width: int, height: int) -> void:
_check_palette_settings_values(palette_name, width, height) _check_palette_settings_values(palette_name, width, height)
current_palette.edit(palette_name, width, height, comment) current_palette.edit(palette_name, width, height, comment)
var palette_path := _current_palette_save() _save_palette()
palettes[palette_path] = current_palette palettes[palette_name] = current_palette
func _delete_palette(path: String, permanent := true) -> void: func _delete_palette(palette: Palette, permanent := true) -> void:
if permanent: if not palette.path.is_empty():
DirAccess.remove_absolute(path) if permanent:
else: DirAccess.remove_absolute(palette.path)
OS.move_to_trash(path) else:
palettes.erase(path) OS.move_to_trash(palette.path)
palettes.erase(palette.name)
func current_palete_delete(permanent := true) -> void: func current_palete_delete(permanent := true) -> void:
_delete_palette(current_palette.resource_path, permanent) _delete_palette(current_palette, permanent)
if palettes.size() > 0: if palettes.size() > 0:
select_palette(palettes.keys()[0]) select_palette(palettes.keys()[0])
@ -230,7 +215,7 @@ func current_palete_delete(permanent := true) -> void:
current_palette = null current_palette = null
func current_palette_add_color(mouse_button: int, start_index: int = 0) -> void: func current_palette_add_color(mouse_button: int, start_index := 0) -> void:
if ( if (
not current_palette.is_full() not current_palette.is_full()
and (mouse_button == MOUSE_BUTTON_LEFT or mouse_button == MOUSE_BUTTON_RIGHT) and (mouse_button == MOUSE_BUTTON_LEFT or mouse_button == MOUSE_BUTTON_RIGHT)
@ -238,7 +223,7 @@ func current_palette_add_color(mouse_button: int, start_index: int = 0) -> void:
# Get color on left or right tool # Get color on left or right tool
var color := Tools.get_assigned_color(mouse_button) var color := Tools.get_assigned_color(mouse_button)
current_palette.add_color(color, start_index) current_palette.add_color(color, start_index)
_current_palette_save() _save_palette()
func current_palette_get_color(index: int) -> Color: func current_palette_get_color(index: int) -> Color:
@ -247,30 +232,30 @@ func current_palette_get_color(index: int) -> Color:
func current_palette_set_color(index: int, color: Color) -> void: func current_palette_set_color(index: int, color: Color) -> void:
current_palette.set_color(index, color) current_palette.set_color(index, color)
_current_palette_save() _save_palette()
func current_palette_delete_color(index: int) -> void: func current_palette_delete_color(index: int) -> void:
current_palette.remove_color(index) current_palette.remove_color(index)
_current_palette_save() _save_palette()
func current_palette_swap_colors(source_index: int, target_index: int) -> void: func current_palette_swap_colors(source_index: int, target_index: int) -> void:
current_palette.swap_colors(source_index, target_index) current_palette.swap_colors(source_index, target_index)
_select_color(MOUSE_BUTTON_LEFT, target_index) _select_color(MOUSE_BUTTON_LEFT, target_index)
_current_palette_save() _save_palette()
func current_palette_copy_colors(from: int, to: int) -> void: func current_palette_copy_colors(from: int, to: int) -> void:
current_palette.copy_colors(from, to) current_palette.copy_colors(from, to)
_current_palette_save() _save_palette()
func current_palette_insert_color(from: int, to: int) -> void: func current_palette_insert_color(from: int, to: int) -> void:
var from_color = current_palette.colors[from] var from_color: Palette.PaletteColor = current_palette.colors[from]
current_palette.remove_color(from) current_palette.remove_color(from)
current_palette.insert_color(to, from_color.color) current_palette.insert_color(to, from_color.color)
_current_palette_save() _save_palette()
func current_palette_get_selected_color_index(mouse_button: int) -> int: func current_palette_get_selected_color_index(mouse_button: int) -> int:
@ -335,9 +320,6 @@ func _load_palettes() -> void:
# get overwritten by those of the same name in user files # get overwritten by those of the same name in user files
search_locations.reverse() search_locations.reverse()
priority_ordered_files.reverse() priority_ordered_files.reverse()
var default_palette_name = Global.config_cache.get_value(
"data", "last_palette", DEFAULT_PALETTE_NAME
)
for i in range(search_locations.size()): for i in range(search_locations.size()):
# If palette is not in palettes write path - make its copy in the write path # If palette is not in palettes write path - make its copy in the write path
var make_copy := false var make_copy := false
@ -345,45 +327,33 @@ func _load_palettes() -> void:
make_copy = true make_copy = true
var base_directory := search_locations[i] var base_directory := search_locations[i]
var palette_files: Array = priority_ordered_files[i] var palette_files := priority_ordered_files[i]
for file_name in palette_files: for file_name in palette_files:
var palette := load(base_directory.path_join(file_name)) as Palette var path := base_directory.path_join(file_name)
if palette: import_palette_from_path(path, make_copy, true)
if make_copy:
_save_palette(palette) # Makes a copy of the palette
palette.resource_name = palette.resource_path.get_file().trim_suffix(".tres")
# On Windows for some reason paths can contain "res://" in front of them which breaks saving
palette.resource_path = palette.resource_path.trim_prefix("res://")
palettes[palette.resource_path] = palette
# Store index of the default palette
if palette.name == default_palette_name:
select_palette(palette.resource_path)
if not current_palette && palettes.size() > 0: if not current_palette && palettes.size() > 0:
select_palette(palettes.keys()[0]) select_palette(palettes.keys()[0])
# This returns an array of arrays, with priorities. ## This returns an array of arrays, with priorities.
# In particular, it takes an array of paths to look for ## In particular, it takes an array of paths to look for
# arrays in, in order of file and palette override priority ## arrays in, in order of file and palette override priority
# such that the files in the first directory override the ## such that the files in the first directory override the second, third, etc.
# second, third, etc. ^.^ ## It returns an array of arrays, where each output array
# It returns an array of arrays, where each output array ## corresponds to the given input array at the same index, and
# corresponds to the given input array at the same index, and ## contains the (relative to the given directory) palette files
# contains the (relative to the given directory) palette files ## to load, excluding all ones already existing in higher-priority directories.
# to load, excluding all ones already existing in higher-priority ## This also means you can run backwards on the result
# directories. nya ## so that palettes with the given palette name in the higher priority
# in particular, this also means you can run backwards on the result ## directories override those set in lower priority directories.
# so that palettes with the given palette name in the higher priority func _get_palette_priority_file_map(looking_paths: PackedStringArray) -> Array[PackedStringArray]:
# directories override those set in lower priority directories :) var final_list: Array[PackedStringArray] = []
func _get_palette_priority_file_map(looking_paths: Array) -> Array:
var final_list := []
# Holds pattern files already found # Holds pattern files already found
var working_file_set: Dictionary = {} var working_file_set: Dictionary = {}
for search_directory in looking_paths: for search_directory in looking_paths:
var to_add_files := [] var to_add_files: PackedStringArray = []
var files = _get_palette_files(search_directory) var files := _get_palette_files(search_directory)
# files to check # files to check
for maybe_to_add in files: for maybe_to_add in files:
if not maybe_to_add in working_file_set: if not maybe_to_add in working_file_set:
@ -394,11 +364,11 @@ func _get_palette_priority_file_map(looking_paths: Array) -> Array:
return final_list return final_list
# Get the palette files in a single directory. ## Get the palette files in a single directory.
# if it does not exist, return [] ## if it does not exist, return []
func _get_palette_files(path: String) -> Array: func _get_palette_files(path: String) -> PackedStringArray:
var dir := DirAccess.open(path) var dir := DirAccess.open(path)
var results := [] var results: PackedStringArray = []
if not is_instance_valid(dir) or not dir.dir_exists(path): if not is_instance_valid(dir) or not dir.dir_exists(path):
return [] return []
@ -411,7 +381,7 @@ func _get_palette_files(path: String) -> Array:
break break
elif ( elif (
(not file_name.begins_with(".")) (not file_name.begins_with("."))
&& file_name.to_lower().ends_with("tres") && file_name.to_lower().ends_with("json")
&& not dir.current_is_dir() && not dir.current_is_dir()
): ):
results.append(file_name) results.append(file_name)
@ -420,19 +390,7 @@ func _get_palette_files(path: String) -> Array:
return results return results
# Locate the highest priority palette by the given relative filename func import_palette_from_path(path: String, make_copy := false, is_initialising := false) -> void:
# If none is found in the directories, then do nothing and return null
func _get_best_palette_file_location(looking_paths: Array, fname: String): # -> String:
var priority_fmap: Array = _get_palette_priority_file_map(looking_paths)
for i in range(looking_paths.size()):
var base_path: String = looking_paths[i]
var the_files: Array = priority_fmap[i]
if the_files.has(fname):
return base_path.path_join(fname)
return null
func import_palette_from_path(path: String) -> void:
if does_palette_exist(path.get_basename().get_file()): if does_palette_exist(path.get_basename().get_file()):
# If there is a palette with same name ignore import for now # If there is a palette with same name ignore import for now
return return
@ -455,31 +413,34 @@ func import_palette_from_path(path: String) -> void:
"json": "json":
if FileAccess.file_exists(path): if FileAccess.file_exists(path):
var text := FileAccess.open(path, FileAccess.READ).get_as_text() var text := FileAccess.open(path, FileAccess.READ).get_as_text()
palette = _import_json_palette(text) palette = Palette.new(path.get_basename().get_file())
palette.path = path
palette.deserialize(text)
import_palette(palette, path.get_file()) if is_instance_valid(palette):
if make_copy:
_save_palette(palette) # Makes a copy of the palette
func import_palette(palette: Palette, file_name: String) -> void: palettes[palette.name] = palette
if does_palette_exist(file_name.get_basename()): var default_palette_name: String = Global.config_cache.get_value(
# If there is a palette with same name ignore import for now "data", "last_palette", DEFAULT_PALETTE_NAME
return )
if palette: if is_initialising:
var palette_path := _save_palette(palette) # Store index of the default palette
palettes[palette_path] = palette if palette.name == default_palette_name:
select_palette(palette_path) select_palette(palette.name)
Global.palette_panel.setup_palettes_selector() else:
Global.palette_panel.select_palette(palette_path) new_palette_imported.emit()
select_palette(palette.name)
else: else:
Global.error_dialog.set_text( Global.error_dialog.set_text(
tr("Can't load file '%s'.\nThis is not a valid palette file.") % [file_name] tr("Can't load file '%s'.\nThis is not a valid palette file.") % [path]
) )
Global.error_dialog.popup_centered() Global.error_dialog.popup_centered()
Global.dialog_open(true) Global.dialog_open(true)
## Refer to app/core/gimppalette-load.c of the GNU Image Manipulation Program for the "living spec"
func _import_gpl(path: String, text: String) -> Palette: func _import_gpl(path: String, text: String) -> Palette:
# Refer to app/core/gimppalette-load.c of the GIMP for the "living spec"
var result: Palette = null var result: Palette = null
var lines := text.split("\n") var lines := text.split("\n")
var line_number := 0 var line_number := 0
@ -488,7 +449,7 @@ func _import_gpl(path: String, text: String) -> Palette:
var colors := PackedColorArray() var colors := PackedColorArray()
for line in lines: for line in lines:
# Check if valid Gimp Palette Library file # Check if the file is a valid palette
if line_number == 0: if line_number == 0:
if not "GIMP Palette" in line: if not "GIMP Palette" in line:
return result return result
@ -514,17 +475,12 @@ func _import_gpl(path: String, text: String) -> Palette:
if color_data.size() >= 4: if color_data.size() >= 4:
# Ignore color name for now - result.add_color(color, color_data[3]) # Ignore color name for now - result.add_color(color, color_data[3])
colors.append(color) colors.append(color)
#
else: else:
colors.append(color) colors.append(color)
line_number += 1 line_number += 1
if line_number > 0: if line_number > 0:
var height := ceili(colors.size() / 8.0) return _fill_imported_palette_with_colors(palette_name, colors, comments)
result = Palette.new(palette_name, 8, height, comments)
for color in colors:
result.add_color(color)
return result return result
@ -539,23 +495,19 @@ func _import_pal_palette(path: String, text: String) -> Palette:
var num_colors := int(lines[2]) var num_colors := int(lines[2])
for i in range(3, num_colors + 3): for i in range(3, num_colors + 3):
var color_data = lines[i].split(" ") var color_data := lines[i].split(" ")
var red: float = color_data[0].to_float() / 255.0 var red := color_data[0].to_float() / 255.0
var green: float = color_data[1].to_float() / 255.0 var green := color_data[1].to_float() / 255.0
var blue: float = color_data[2].to_float() / 255.0 var blue := color_data[2].to_float() / 255.0
var color := Color(red, green, blue) var color := Color(red, green, blue)
colors.append(color) colors.append(color)
var height := ceili(colors.size() / 8.0) return _fill_imported_palette_with_colors(path.get_basename().get_file(), colors)
result = Palette.new(path.get_basename().get_file(), 8, height)
for color in colors:
result.add_color(color)
return result
func _import_image_palette(path: String, image: Image) -> Palette: func _import_image_palette(path: String, image: Image) -> Palette:
var colors := [] var colors: PackedColorArray = []
var height := image.get_height() var height := image.get_height()
var width := image.get_width() var width := image.get_width()
@ -566,36 +518,17 @@ func _import_image_palette(path: String, image: Image) -> Palette:
if !colors.has(color): if !colors.has(color):
colors.append(color) colors.append(color)
var palette_height := ceili(colors.size() / 8.0) return _fill_imported_palette_with_colors(path.get_basename().get_file(), colors)
var result: Palette = Palette.new(path.get_basename().get_file(), 8, palette_height)
## Fills a new [Palette] with colors. Used when importing files.
## TODO: Somehow let the users choose the fixed height or width, instead of hardcoding 8.
func _fill_imported_palette_with_colors(
palette_name: String, colors: PackedColorArray, comment := ""
) -> Palette:
var height := ceili(colors.size() / 8.0)
var result := Palette.new(palette_name, 8, height, comment)
for color in colors: for color in colors:
result.add_color(color) result.add_color(color)
return result return result
## Import of deprecated older json palette format
func _import_json_palette(text: String) -> Palette:
var result := Palette.new()
var test_json_conv := JSON.new()
test_json_conv.parse(text)
var result_json = test_json_conv.get_data()
if result_json.error != OK: # If parse has errors
printerr("JSON palette import error")
printerr("Error: ", result_json.error)
printerr("Error Line: ", result_json.error_line)
printerr("Error String: ", result_json.error_string)
result = null
else: # If parse OK
var data = result_json.result
if data.has("name"): # If data is 'valid' palette file
result.name = data.name
if data.has("comments"):
result.comment = data.comments
if data.has("colors"):
for color_data in data.colors:
var color := Color(color_data.data)
result.add_color(color)
return result

View file

@ -430,8 +430,6 @@ func assign_color(color: Color, button: int, change_alpha := true) -> void:
_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) color_changed.emit(color, button)
# If current palette has that color then select that color
Global.palette_panel.palette_grid.find_and_select_color(button, color)
func get_assigned_color(button: int) -> Color: func get_assigned_color(button: int) -> Color:

View file

@ -1,11 +1,15 @@
extends ConfirmationDialog extends ConfirmationDialog
# Emitted when user confirms their changes ## Emitted when the user confirms their changes
signal saved(name, comment, width, height) signal saved(name: String, comment: String, width: int, height: int)
## Emitted when the user deletes a palette
signal deleted signal deleted
## Emitted when the user exports a palette
signal exported(path: String)
const DELETE_ACTION := "delete" const EXPORT_ACTION := &"export"
const BIN_ACTION := "trash" const DELETE_ACTION := &"delete"
const BIN_ACTION := &"trash"
# Keeps original size of edited palette # Keeps original size of edited palette
var origin_width := 0 var origin_width := 0
@ -22,11 +26,13 @@ var old_name := ""
@onready var size_reduced_warning := $VBoxContainer/SizeReducedWarning @onready var size_reduced_warning := $VBoxContainer/SizeReducedWarning
@onready var already_exists_warning := $VBoxContainer/AlreadyExistsWarning @onready var already_exists_warning := $VBoxContainer/AlreadyExistsWarning
@onready var delete_confirmation := $DeleteConfirmation @onready var delete_confirmation := $DeleteConfirmation
@onready var export_file_dialog: FileDialog = $ExportFileDialog
func _ready() -> void: func _ready() -> void:
# Add delete button to edit palette dialog # Add delete and export buttons to edit palette dialog
add_button(tr("Delete"), false, DELETE_ACTION) add_button(tr("Delete"), false, DELETE_ACTION)
add_button(tr("Export"), false, EXPORT_ACTION)
delete_confirmation.add_button(tr("Move to Trash"), false, BIN_ACTION) delete_confirmation.add_button(tr("Move to Trash"), false, BIN_ACTION)
@ -36,7 +42,8 @@ func open(current_palette: Palette) -> void:
comment_input.text = current_palette.comment comment_input.text = current_palette.comment
width_input.value = current_palette.width width_input.value = current_palette.width
height_input.value = current_palette.height height_input.value = current_palette.height
path_input.text = current_palette.resource_path path_input.text = current_palette.path
export_file_dialog.current_file = current_palette.name
# Store original size so it can be compared with changed values # Store original size so it can be compared with changed values
# and warning can be shown if it is reduced # and warning can be shown if it is reduced
@ -79,9 +86,11 @@ func _on_EditPaletteDialog_confirmed() -> void:
saved.emit(name_input.text, comment_input.text, width_input.value, height_input.value) saved.emit(name_input.text, comment_input.text, width_input.value, height_input.value)
func _on_EditPaletteDialog_custom_action(action: String) -> void: func _on_EditPaletteDialog_custom_action(action: StringName) -> void:
if action == DELETE_ACTION: if action == DELETE_ACTION:
delete_confirmation.popup_centered() delete_confirmation.popup_centered()
elif action == EXPORT_ACTION:
export_file_dialog.popup_centered()
func _on_delete_confirmation_confirmed() -> void: func _on_delete_confirmation_confirmed() -> void:
@ -97,7 +106,7 @@ func _on_delete_confirmation_custom_action(action: StringName) -> void:
hide() hide()
func _on_size_value_changed(_value): func _on_size_value_changed(_value: int):
# Toggle resize warning label if palette size was reduced # Toggle resize warning label if palette size was reduced
var size_decreased: bool = ( var size_decreased: bool = (
height_input.value < origin_height or width_input.value < origin_width height_input.value < origin_height or width_input.value < origin_width
@ -105,7 +114,7 @@ func _on_size_value_changed(_value):
toggle_size_reduced_warning(size_decreased) toggle_size_reduced_warning(size_decreased)
func _on_Name_text_changed(new_name): func _on_Name_text_changed(new_name: String):
if old_name != new_name: if old_name != new_name:
if Palettes.does_palette_exist(new_name): if Palettes.does_palette_exist(new_name):
toggle_already_exists_warning(true) toggle_already_exists_warning(true)
@ -115,3 +124,7 @@ func _on_Name_text_changed(new_name):
# Disable ok button on empty name # Disable ok button on empty name
if new_name == "": if new_name == "":
get_ok_button().disabled = true get_ok_button().disabled = true
func _on_export_file_dialog_file_selected(path: String) -> void:
exported.emit(path)

View file

@ -4,7 +4,7 @@
[node name="EditPaletteDialog" type="ConfirmationDialog"] [node name="EditPaletteDialog" type="ConfirmationDialog"]
title = "Edit Palette" title = "Edit Palette"
size = Vector2i(409, 359) size = Vector2i(421, 371)
exclusive = false exclusive = false
popup_window = true popup_window = true
script = ExtResource("1") script = ExtResource("1")
@ -16,7 +16,7 @@ anchor_bottom = 1.0
offset_left = 8.0 offset_left = 8.0
offset_top = 8.0 offset_top = 8.0
offset_right = -8.0 offset_right = -8.0
offset_bottom = -45.0 offset_bottom = -49.0
[node name="PaletteMetadata" type="GridContainer" parent="VBoxContainer"] [node name="PaletteMetadata" type="GridContainer" parent="VBoxContainer"]
layout_mode = 2 layout_mode = 2
@ -77,6 +77,7 @@ text = "Path:"
custom_minimum_size = Vector2(0, 50) custom_minimum_size = Vector2(0, 50)
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
editable = false
[node name="SizeReducedWarning" type="Label" parent="VBoxContainer"] [node name="SizeReducedWarning" type="Label" parent="VBoxContainer"]
custom_minimum_size = Vector2(0, 27) custom_minimum_size = Vector2(0, 27)
@ -114,6 +115,11 @@ text = "Delete Palette?"
horizontal_alignment = 1 horizontal_alignment = 1
vertical_alignment = 1 vertical_alignment = 1
[node name="ExportFileDialog" type="FileDialog" parent="."]
size = Vector2i(677, 400)
access = 2
filters = PackedStringArray("*.png ; PNG Image", "*.jpg,*.jpeg ; JPEG Image", "*.webp ; WebP Image")
[connection signal="confirmed" from="." to="." method="_on_EditPaletteDialog_confirmed"] [connection signal="confirmed" from="." to="." method="_on_EditPaletteDialog_confirmed"]
[connection signal="custom_action" from="." to="." method="_on_EditPaletteDialog_custom_action"] [connection signal="custom_action" from="." to="." method="_on_EditPaletteDialog_custom_action"]
[connection signal="visibility_changed" from="." to="." method="_on_EditPaletteDialog_visibility_changed"] [connection signal="visibility_changed" from="." to="." method="_on_EditPaletteDialog_visibility_changed"]
@ -122,3 +128,4 @@ vertical_alignment = 1
[connection signal="value_changed" from="VBoxContainer/PaletteMetadata/Height" to="." method="_on_size_value_changed"] [connection signal="value_changed" from="VBoxContainer/PaletteMetadata/Height" to="." method="_on_size_value_changed"]
[connection signal="confirmed" from="DeleteConfirmation" to="." method="_on_delete_confirmation_confirmed"] [connection signal="confirmed" from="DeleteConfirmation" to="." method="_on_delete_confirmation_confirmed"]
[connection signal="custom_action" from="DeleteConfirmation" to="." method="_on_delete_confirmation_custom_action"] [connection signal="custom_action" from="DeleteConfirmation" to="." method="_on_delete_confirmation_custom_action"]
[connection signal="file_selected" from="ExportFileDialog" to="." method="_on_export_file_dialog_file_selected"]

View file

@ -1,46 +1,65 @@
class_name Palette class_name Palette
extends Resource extends RefCounted
const DEFAULT_WIDTH := 8 const DEFAULT_WIDTH := 8
const DEFAULT_HEIGHT := 8 const DEFAULT_HEIGHT := 8
# Metadata # Metadata
@export var name := "Custom Palette" var name := "Custom Palette"
@export var comment := "" var comment := ""
var path := ""
# Grid size
@export var width := DEFAULT_WIDTH
@export var height := DEFAULT_HEIGHT
## Sparse colors dictionary - actual color position in the palette is determined by its index
@export var colors := {}
## The width of the grid
var width := DEFAULT_WIDTH
## The height of the grid
var height := DEFAULT_HEIGHT
## Sparse colors dictionary of [int] and [PaletteColor]
## Actual color position in the palette is determined by its index
var colors := {}
## How many colors fit in palette grid ## How many colors fit in palette grid
@export var colors_max := 0 var colors_max := 0
class PaletteColor:
var color := Color.TRANSPARENT
var index := -1
func _init(init_color := Color.BLACK, init_index := -1) -> void:
color = init_color
index = init_index
func duplicate() -> PaletteColor:
return PaletteColor.new(color, index)
func serialize() -> Dictionary:
return {"color": color, "index": index}
func deserialize(dict: Dictionary) -> void:
if dict.has("color"):
color = dict["color"]
if dict.has("index"):
color = dict["index"]
func _init( func _init(
init_name: String = "Custom Palette", _name := "Custom Palette", _width := DEFAULT_WIDTH, _height := DEFAULT_HEIGHT, _comment := ""
init_width: int = DEFAULT_WIDTH,
init_height: int = DEFAULT_HEIGHT,
init_comment: String = ""
) -> void: ) -> void:
name = init_name name = _name
comment = init_comment comment = _comment
width = init_width width = _width
height = init_height height = _height
colors_max = init_width * init_height colors_max = _width * _height
colors = {} colors = {}
func edit(new_name: String, new_width: int, new_height: int, new_comment: String) -> void: func edit(new_name: String, new_width: int, new_height: int, new_comment: String) -> void:
var old_width = width var old_width := width
width = new_width width = new_width
height = new_height height = new_height
name = new_name name = new_name
comment = new_comment comment = new_comment
var old_colors_max = colors_max var old_colors_max := colors_max
colors_max = width * height colors_max = width * height
if colors_max < old_colors_max: if colors_max < old_colors_max:
@ -54,14 +73,65 @@ func edit(new_name: String, new_width: int, new_height: int, new_comment: String
reindex_colors_on_width_increase(old_width) reindex_colors_on_width_increase(old_width)
func duplicate() -> Palette:
var new_palette := Palette.new(name, width, height, comment)
var new_colors := colors.duplicate(true)
new_palette.colors = new_colors
return new_palette
func _serialize() -> String:
var serialize_data := {"comment": comment, "colors": [], "width": width, "height": height}
for color in colors:
serialize_data.colors.push_back(colors[color].serialize())
return JSON.stringify(serialize_data, " ")
func deserialize(json_string: String) -> void:
var test_json_conv := JSON.new()
var err := test_json_conv.parse(json_string)
if err != OK: # If parse has errors
printerr("JSON palette import error")
printerr("Error: ", err)
printerr("Error Line: ", test_json_conv.get_error_line())
printerr("Error String: ", test_json_conv.get_error_message())
return
var data = test_json_conv.get_data()
if not typeof(data) == TYPE_DICTIONARY:
return
if data.has("comment"):
comment = data.comment
if data.has("colors"):
for color_data in data.colors:
var color := str_to_var("Color" + color_data["color"]) as Color
var index := color_data["index"] as int
var palette_color := PaletteColor.new(color, index)
colors[index] = palette_color
if data.has("width"):
width = data.width
if data.has("height"):
height = data.height
colors_max = width * height
func save_to_file() -> Error:
var file := FileAccess.open(path, FileAccess.WRITE)
if not is_instance_valid(file):
return FileAccess.get_open_error()
file.store_string(_serialize())
file.close()
return OK
## Iterates all colors from lowest index and reindexes them so they start at zero index ## Iterates all colors from lowest index and reindexes them so they start at zero index
## Remove trailing removes all colors that are over colors_max limit and thus don't fit into grid ## Remove trailing removes all colors that are over colors_max limit and thus don't fit into grid
func reindex_colors_on_size_reduce(remove_trailing: bool) -> void: func reindex_colors_on_size_reduce(remove_trailing: bool) -> void:
var sorted_colors_indexes = colors.keys() var sorted_colors_indexes := colors.keys()
sorted_colors_indexes.sort() sorted_colors_indexes.sort()
var new_index := 0
var new_index = 0 for old_index: int in sorted_colors_indexes:
for old_index in sorted_colors_indexes:
# Color cannot fit into grid anymore - erase it # Color cannot fit into grid anymore - erase it
if remove_trailing and new_index >= colors_max: if remove_trailing and new_index >= colors_max:
colors.erase(old_index) colors.erase(old_index)
@ -78,19 +148,18 @@ func reindex_colors_on_size_reduce(remove_trailing: bool) -> void:
## Adds difference of old and new width to color indexes ## Adds difference of old and new width to color indexes
## so they remain on the same position as before resize ## so they remain on the same position as before resize
func reindex_colors_on_width_increase(old_width: int) -> void: func reindex_colors_on_width_increase(old_width: int) -> void:
var sorted_colors_indexes = colors.keys() var sorted_colors_indexes := colors.keys()
sorted_colors_indexes.sort() sorted_colors_indexes.sort()
var new_colors := {}
var new_colors = {} for old_index: int in sorted_colors_indexes:
for old_index in sorted_colors_indexes: var new_index := old_index + (width - old_width) * (old_index / old_width)
var new_index: int = old_index + (width - old_width) * (old_index / old_width)
new_colors[new_index] = colors[old_index] new_colors[new_index] = colors[old_index]
colors = new_colors colors = new_colors
## Adds new color to the first empty swatch ## Adds new color to the first empty swatch
func add_color(new_color: Color, start_index: int = 0) -> void: func add_color(new_color: Color, start_index := 0) -> void:
if start_index >= colors_max: if start_index >= colors_max:
return return
@ -107,7 +176,7 @@ func add_color(new_color: Color, start_index: int = 0) -> void:
## Returns color at index or null if no color exists ## Returns color at index or null if no color exists
func get_color(index: int): func get_color(index: int):
var palette_color = colors.get(index) var palette_color: PaletteColor = colors.get(index)
if palette_color != null: if palette_color != null:
return palette_color.color return palette_color.color
return null return null
@ -115,8 +184,8 @@ func get_color(index: int):
## Changes color data ## Changes color data
func set_color(index: int, new_color: Color) -> void: func set_color(index: int, new_color: Color) -> void:
if self.colors.has(index): if colors.has(index):
self.colors[index].color = new_color colors[index].color = new_color
## Removes a color at the specified index ## Removes a color at the specified index
@ -130,7 +199,7 @@ func insert_color(index: int, new_color: Color) -> void:
var c := PaletteColor.new(new_color, index) var c := PaletteColor.new(new_color, index)
# If insert happens on non empty swatch recursively move the original color # If insert happens on non empty swatch recursively move the original color
# and every other color to its right one swatch to right # and every other color to its right one swatch to right
if colors.get(index) != null: if colors[index] != null:
move_right(index) move_right(index)
colors[index] = c colors[index] = c
@ -144,16 +213,16 @@ func move_right(index: int) -> void:
colors_max = width * height colors_max = width * height
# If swatch to right to this color is not empty move that color right too # If swatch to right to this color is not empty move that color right too
if colors.get(index + 1) != null: if colors[index + 1] != null:
move_right(index + 1) move_right(index + 1)
colors[index + 1] = colors.get(index) colors[index + 1] = colors[index]
## Swaps two colors ## Swaps two colors
func swap_colors(from_index: int, to_index: int) -> void: func swap_colors(from_index: int, to_index: int) -> void:
var from_color = colors.get(from_index) var from_color: PaletteColor = colors.get(from_index)
var to_color = colors.get(to_index) var to_color: PaletteColor = colors.get(to_index)
if not from_color and to_color: if not from_color and to_color:
colors[from_index] = to_color colors[from_index] = to_color
@ -173,19 +242,19 @@ func swap_colors(from_index: int, to_index: int) -> void:
## Copies color ## Copies color
func copy_colors(from_index: int, to_index: int) -> void: func copy_colors(from_index: int, to_index: int) -> void:
# Only allow copy of existing colors # Only allow copy of existing colors
if colors.has(from_index): if colors[from_index] != null:
colors[to_index] = colors[from_index].duplicate() colors[to_index] = colors[from_index].duplicate()
colors[to_index].index = to_index colors[to_index].index = to_index
## True if all swatches are occupied ## True if all swatches are occupied
func is_full() -> bool: func is_full() -> bool:
return self.colors.size() >= self.colors_max return colors.size() >= colors_max
## True if palette has no colors ## True if palette has no colors
func is_empty() -> bool: func is_empty() -> bool:
return self.colors.size() == 0 return colors.size() == 0
func has_theme_color(color: Color) -> bool: func has_theme_color(color: Color) -> bool:
@ -195,13 +264,15 @@ func has_theme_color(color: Color) -> bool:
return false return false
## Sets name that is used to save the palette to disk
func set_resource_name(new_resource_name: String) -> void:
# Store palette path name only with valid path characters
resource_name = Palette.strip_unvalid_characters(new_resource_name)
static func strip_unvalid_characters(string_to_strip: String) -> String: static func strip_unvalid_characters(string_to_strip: String) -> String:
var regex := RegEx.new() var regex := RegEx.new()
regex.compile("[^a-zA-Z0-9_]+") regex.compile("[^a-zA-Z0-9_]+")
return regex.sub(string_to_strip, "", true) return regex.sub(string_to_strip, "", true)
func convert_to_image() -> Image:
var image := Image.create(colors_max, 1, false, Image.FORMAT_RGBA8)
for i in colors_max:
if colors.has(i):
image.set_pixel(i, 0, colors[i].color)
return image

View file

@ -1,12 +0,0 @@
class_name PaletteColor
extends Resource
const UNSET_INDEX := -1
@export var color: Color = Color.TRANSPARENT
@export var index := UNSET_INDEX
func _init(init_color: Color = Color.BLACK, init_index: int = UNSET_INDEX) -> void:
color = init_color
index = init_index

View file

@ -1,9 +1,9 @@
class_name PaletteGrid class_name PaletteGrid
extends GridContainer extends GridContainer
signal swatch_pressed(mouse_button, index) signal swatch_pressed(mouse_button: int, index: int)
signal swatch_double_clicked(mouse_button, index, position) signal swatch_double_clicked(mouse_button: int, index: int, position: Vector2)
signal swatch_dropped(source_index, target_index) signal swatch_dropped(source_index: int, target_index: int)
const PALETTE_SWATCH_SCENE := preload("res://src/Palette/PaletteSwatch.tscn") const PALETTE_SWATCH_SCENE := preload("res://src/Palette/PaletteSwatch.tscn")
const DEFAULT_SWATCH_SIZE := Vector2(26, 26) const DEFAULT_SWATCH_SIZE := Vector2(26, 26)
@ -12,13 +12,14 @@ const MAX_SWATCH_SIZE := Vector2(64, 64)
var swatches: Array[PaletteSwatch] = [] var swatches: Array[PaletteSwatch] = []
var current_palette: Palette = null var current_palette: Palette = null
var grid_window_origin := Vector2.ZERO var grid_window_origin := Vector2i.ZERO
var grid_size := Vector2.ZERO var grid_size := Vector2i.ZERO
var swatch_size := DEFAULT_SWATCH_SIZE var swatch_size := DEFAULT_SWATCH_SIZE
func _ready() -> void: func _ready() -> void:
swatch_size = Global.config_cache.get_value("palettes", "swatch_size", DEFAULT_SWATCH_SIZE) swatch_size = Global.config_cache.get_value("palettes", "swatch_size", DEFAULT_SWATCH_SIZE)
Tools.color_changed.connect(find_and_select_color)
func set_palette(new_palette: Palette) -> void: func set_palette(new_palette: Palette) -> void:
@ -32,7 +33,7 @@ func set_palette(new_palette: Palette) -> void:
func setup_swatches() -> void: func setup_swatches() -> void:
# Columns cannot be 0 # Columns cannot be 0
columns = 1.0 if grid_size.x == 0.0 else grid_size.x columns = 1 if grid_size.x == 0 else grid_size.x
if grid_size.x * grid_size.y > swatches.size(): if grid_size.x * grid_size.y > swatches.size():
for i in range(swatches.size(), grid_size.x * grid_size.y): for i in range(swatches.size(), grid_size.x * grid_size.y):
var swatch := PALETTE_SWATCH_SCENE.instantiate() as PaletteSwatch var swatch := PALETTE_SWATCH_SCENE.instantiate() as PaletteSwatch
@ -67,7 +68,7 @@ func draw_palette() -> void:
for i in range(grid_size.x): for i in range(grid_size.x):
var grid_index := i + grid_size.x * j var grid_index := i + grid_size.x * j
var index := convert_grid_index_to_palette_index(grid_index) var index := convert_grid_index_to_palette_index(grid_index)
var swatch = swatches[grid_index] var swatch := swatches[grid_index]
swatch.show_left_highlight = false swatch.show_left_highlight = false
swatch.show_right_highlight = false swatch.show_right_highlight = false
var color = current_palette.get_color(index) var color = current_palette.get_color(index)
@ -79,13 +80,15 @@ func draw_palette() -> void:
swatch.empty = true swatch.empty = true
func scroll_palette(origin: Vector2) -> void: func scroll_palette(origin: Vector2i) -> void:
grid_window_origin = origin grid_window_origin = origin
draw_palette() draw_palette()
func find_and_select_color(mouse_button: int, target_color: Color) -> void: ## Called when the color changes, either the left or the right, determined by [param mouse_button].
var old_index = Palettes.current_palette_get_selected_color_index(mouse_button) ## If current palette has [param target_color] as a [Color], then select it.
func find_and_select_color(target_color: Color, mouse_button: int) -> void:
var old_index := Palettes.current_palette_get_selected_color_index(mouse_button)
for color_ind in swatches.size(): for color_ind in swatches.size():
if target_color.is_equal_approx(swatches[color_ind].color): if target_color.is_equal_approx(swatches[color_ind].color):
select_swatch(mouse_button, color_ind, old_index) select_swatch(mouse_button, color_ind, old_index)
@ -99,8 +102,8 @@ func find_and_select_color(mouse_button: int, target_color: Color) -> void:
## Displays a left/right highlight over a swatch ## Displays a left/right highlight over a swatch
func select_swatch(mouse_button: int, palette_index: int, old_palette_index: int) -> void: func select_swatch(mouse_button: int, palette_index: int, old_palette_index: int) -> void:
var index = convert_palette_index_to_grid_index(palette_index) var index := convert_palette_index_to_grid_index(palette_index)
var old_index = convert_palette_index_to_grid_index(old_palette_index) var old_index := convert_palette_index_to_grid_index(old_palette_index)
if index >= 0 and index < swatches.size(): if index >= 0 and index < swatches.size():
# Remove highlight from old index swatch and add to index swatch # Remove highlight from old index swatch and add to index swatch
if old_index >= 0 and old_index < swatches.size(): if old_index >= 0 and old_index < swatches.size():
@ -110,31 +113,24 @@ func select_swatch(mouse_button: int, palette_index: int, old_palette_index: int
func unselect_swatch(mouse_button: int, palette_index: int) -> void: func unselect_swatch(mouse_button: int, palette_index: int) -> void:
var index = convert_palette_index_to_grid_index(palette_index) var index := convert_palette_index_to_grid_index(palette_index)
if index >= 0 and index < swatches.size(): if index >= 0 and index < swatches.size():
swatches[index].show_selected_highlight(false, mouse_button) swatches[index].show_selected_highlight(false, mouse_button)
func set_swatch_color(palette_index: int, color: Color) -> void: func set_swatch_color(palette_index: int, color: Color) -> void:
var index = convert_palette_index_to_grid_index(palette_index) var index := convert_palette_index_to_grid_index(palette_index)
if index >= 0 and index < swatches.size(): if index >= 0 and index < swatches.size():
swatches[index].color = color swatches[index].color = color
func get_swatch_color(palette_index: int) -> Color: func get_swatch_color(palette_index: int) -> Color:
var index = convert_palette_index_to_grid_index(palette_index) var index := convert_palette_index_to_grid_index(palette_index)
if index >= 0 and index < swatches.size(): if index >= 0 and index < swatches.size():
return swatches[index].color return swatches[index].color
return Color.TRANSPARENT return Color.TRANSPARENT
## Used to reload empty swatch color from a theme
func reset_empty_swatches_color() -> void:
for swatch in swatches:
if swatch.empty:
swatch.empty = true
## Grid index adds grid window origin ## Grid index adds grid window origin
func convert_grid_index_to_palette_index(index: int) -> int: func convert_grid_index_to_palette_index(index: int) -> int:
return ( return (
@ -178,12 +174,12 @@ func change_swatch_size(size_diff: Vector2) -> void:
func _on_PaletteSwatch_pressed(mouse_button: int, index: int) -> void: func _on_PaletteSwatch_pressed(mouse_button: int, index: int) -> void:
var palette_index = convert_grid_index_to_palette_index(index) var palette_index := convert_grid_index_to_palette_index(index)
swatch_pressed.emit(mouse_button, palette_index) swatch_pressed.emit(mouse_button, palette_index)
func _on_PaletteSwatch_double_clicked(mouse_button: int, pos: Vector2, index: int) -> void: func _on_PaletteSwatch_double_clicked(mouse_button: int, pos: Vector2, index: int) -> void:
var palette_index = convert_grid_index_to_palette_index(index) var palette_index := convert_grid_index_to_palette_index(index)
swatch_double_clicked.emit(mouse_button, palette_index, pos) swatch_double_clicked.emit(mouse_button, palette_index, pos)

View file

@ -8,7 +8,7 @@ var edited_swatch_index := -1
var edited_swatch_color := Color.TRANSPARENT var edited_swatch_color := Color.TRANSPARENT
@onready var palette_select := $"%PaletteSelect" @onready var palette_select := $"%PaletteSelect"
@onready var palette_grid := $"%PaletteGrid" @onready var palette_grid := $"%PaletteGrid" as PaletteGrid
@onready var palette_scroll := $"%PaletteScroll" @onready var palette_scroll := $"%PaletteScroll"
@onready var add_color_button := $"%AddColor" @onready var add_color_button := $"%AddColor"
@ -17,11 +17,13 @@ var edited_swatch_color := Color.TRANSPARENT
@onready var edit_palette_dialog := $"%EditPaletteDialog" @onready var edit_palette_dialog := $"%EditPaletteDialog"
@onready var create_palette_dialog := $"%CreatePaletteDialog" @onready var create_palette_dialog := $"%CreatePaletteDialog"
# Color picker button itself is hidden but its popup is used to edit color swatches ## This color picker button itself is hidden, but its popup is used to edit color swatches.
@onready var hidden_color_picker := $"%HiddenColorPickerButton" as ColorPickerButton @onready var hidden_color_picker := $"%HiddenColorPickerButton" as ColorPickerButton
func _ready() -> void: func _ready() -> void:
Palettes.palette_selected.connect(select_palette)
Palettes.new_palette_imported.connect(setup_palettes_selector)
Tools.color_changed.connect(_color_changed) Tools.color_changed.connect(_color_changed)
setup_palettes_selector() setup_palettes_selector()
@ -39,24 +41,23 @@ func setup_palettes_selector() -> void:
palette_select.clear() palette_select.clear()
var id := 0 var id := 0
for palette_path in Palettes.get_palettes(): for palette_name in Palettes.palettes:
# Add palette selector item # Add palette selector item
palette_select.add_item(Palettes.get_palettes()[palette_path].name, id) palette_select.add_item(Palettes.palettes[palette_name].name, id)
# Map palette paths to item id's and otherwise # Map palette paths to item id's and otherwise
palettes_path_id[palette_path] = id palettes_path_id[palette_name] = id
palettes_id_path[id] = palette_path palettes_id_path[id] = palette_name
id += 1 id += 1
func select_palette(palette_path: String) -> void: func select_palette(palette_name: String) -> void:
var palette_id = palettes_path_id.get(palette_path) var palette_id = palettes_path_id.get(palette_name)
if palette_id != null: if palette_id != null:
palette_select.selected = palette_id palette_select.selected = palette_id
Palettes.select_palette(palette_path) palette_grid.set_palette(Palettes.current_palette)
palette_grid.set_palette(Palettes.get_current_palette())
palette_scroll.resize_grid() palette_scroll.resize_grid()
palette_scroll.set_sliders(Palettes.get_current_palette(), palette_grid.grid_window_origin) palette_scroll.set_sliders(Palettes.current_palette, palette_grid.grid_window_origin)
var left_selected := Palettes.current_palette_get_selected_color_index(MOUSE_BUTTON_LEFT) var left_selected := Palettes.current_palette_get_selected_color_index(MOUSE_BUTTON_LEFT)
var right_selected := Palettes.current_palette_get_selected_color_index(MOUSE_BUTTON_RIGHT) var right_selected := Palettes.current_palette_get_selected_color_index(MOUSE_BUTTON_RIGHT)
@ -66,16 +67,10 @@ func select_palette(palette_path: String) -> void:
toggle_add_delete_buttons() toggle_add_delete_buttons()
## Has to be called on every Pixelorama theme change ## Select and display current palette
func reset_empty_palette_swatches_color() -> void:
palette_grid.reset_empty_swatches_color()
func redraw_current_palette() -> void: func redraw_current_palette() -> void:
# Select and display current palette if is_instance_valid(Palettes.current_palette):
var current_palette := Palettes.get_current_palette() Palettes.select_palette(Palettes.current_palette.name)
if current_palette:
select_palette(current_palette.resource_path)
add_color_button.show() add_color_button.show()
delete_color_button.show() delete_color_button.show()
else: else:
@ -105,7 +100,7 @@ func _on_EditPalette_pressed() -> void:
func _on_PaletteSelect_item_selected(index: int) -> void: func _on_PaletteSelect_item_selected(index: int) -> void:
select_palette(palettes_id_path.get(index)) Palettes.select_palette(palettes_id_path.get(index))
func _on_AddColor_gui_input(event: InputEvent) -> void: func _on_AddColor_gui_input(event: InputEvent) -> void:
@ -120,7 +115,7 @@ func _on_AddColor_gui_input(event: InputEvent) -> void:
# Gets the grid index that corresponds to the top left of current grid window # Gets the grid index that corresponds to the top left of current grid window
# Color will be added at the start of the currently scrolled part of palette # Color will be added at the start of the currently scrolled part of palette
# - not the absolute beginning of palette # - not the absolute beginning of palette
var start_index = palette_grid.convert_grid_index_to_palette_index(0) var start_index := palette_grid.convert_grid_index_to_palette_index(0)
Palettes.current_palette_add_color(event.button_index, start_index) Palettes.current_palette_add_color(event.button_index, start_index)
redraw_current_palette() redraw_current_palette()
toggle_add_delete_buttons() toggle_add_delete_buttons()
@ -129,7 +124,7 @@ func _on_AddColor_gui_input(event: InputEvent) -> void:
func _on_DeleteColor_gui_input(event: InputEvent) -> void: func _on_DeleteColor_gui_input(event: InputEvent) -> void:
if Palettes.is_any_palette_selected(): if Palettes.is_any_palette_selected():
if event is InputEventMouseButton and event.pressed: if event is InputEventMouseButton and event.pressed:
var selected_color_index = Palettes.current_palette_get_selected_color_index( var selected_color_index := Palettes.current_palette_get_selected_color_index(
event.button_index event.button_index
) )
@ -210,8 +205,8 @@ func _on_ColorPicker_color_changed(color: Color) -> void:
Tools.assign_color(color, MOUSE_BUTTON_RIGHT) Tools.assign_color(color, MOUSE_BUTTON_RIGHT)
func _on_HiddenColorPickerButton_popup_closed(): ## Saves edited swatch to palette file when color selection dialog is closed
# Saves edited swatch to palette file when color selection dialog is closed func _on_HiddenColorPickerButton_popup_closed() -> void:
Palettes.current_palette_set_color(edited_swatch_index, edited_swatch_color) Palettes.current_palette_set_color(edited_swatch_index, edited_swatch_color)
@ -222,10 +217,9 @@ func _on_EditPaletteDialog_deleted(permanent: bool) -> void:
func _color_changed(_color: Color, button: int) -> void: func _color_changed(_color: Color, button: int) -> void:
if hidden_color_picker.get_popup().visible == false and Palettes.get_current_palette(): if not hidden_color_picker.get_popup().visible and is_instance_valid(Palettes.current_palette):
# Unselect swatches when tools color is changed # Unselect swatches when tools color is changed
var swatch_to_unselect := -1 var swatch_to_unselect := -1
if button == MOUSE_BUTTON_LEFT: if button == MOUSE_BUTTON_LEFT:
swatch_to_unselect = Palettes.left_selected_color swatch_to_unselect = Palettes.left_selected_color
Palettes.left_selected_color = -1 Palettes.left_selected_color = -1
@ -234,3 +228,17 @@ func _color_changed(_color: Color, button: int) -> void:
Palettes.right_selected_color = -1 Palettes.right_selected_color = -1
palette_grid.unselect_swatch(button, swatch_to_unselect) palette_grid.unselect_swatch(button, swatch_to_unselect)
func _on_edit_palette_dialog_exported(path: String) -> void:
var extension := path.get_extension()
match extension:
"png":
var image := Palettes.current_palette.convert_to_image()
image.save_png(path)
"jpg", "jpeg":
var image := Palettes.current_palette.convert_to_image()
image.save_jpg(path)
"webp":
var image := Palettes.current_palette.convert_to_image()
image.save_webp(path)

View file

@ -160,6 +160,8 @@ unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
horizontal_scroll_mode = 3
vertical_scroll_mode = 3
[node name="PaletteGrid" type="GridContainer" parent="PaletteVBoxContainer/SwatchesContainer/PaletteScroll/HBoxContainer/VBoxContainer/ScrollContainer"] [node name="PaletteGrid" type="GridContainer" parent="PaletteVBoxContainer/SwatchesContainer/PaletteScroll/HBoxContainer/VBoxContainer/ScrollContainer"]
unique_name_in_owner = true unique_name_in_owner = true
@ -215,6 +217,7 @@ layout_mode = 2
[connection signal="value_changed" from="PaletteVBoxContainer/SwatchesContainer/PaletteScroll/HBoxContainer/VBoxContainer/HScrollBar" to="PaletteVBoxContainer/SwatchesContainer/PaletteScroll" method="_on_HSlider_value_changed"] [connection signal="value_changed" from="PaletteVBoxContainer/SwatchesContainer/PaletteScroll/HBoxContainer/VBoxContainer/HScrollBar" to="PaletteVBoxContainer/SwatchesContainer/PaletteScroll" method="_on_HSlider_value_changed"]
[connection signal="value_changed" from="PaletteVBoxContainer/SwatchesContainer/PaletteScroll/HBoxContainer/MarginContainer/VScrollBar" to="PaletteVBoxContainer/SwatchesContainer/PaletteScroll" method="_on_VSlider_value_changed"] [connection signal="value_changed" from="PaletteVBoxContainer/SwatchesContainer/PaletteScroll/HBoxContainer/MarginContainer/VScrollBar" to="PaletteVBoxContainer/SwatchesContainer/PaletteScroll" method="_on_VSlider_value_changed"]
[connection signal="deleted" from="EditPaletteDialog" to="." method="_on_EditPaletteDialog_deleted"] [connection signal="deleted" from="EditPaletteDialog" to="." method="_on_EditPaletteDialog_deleted"]
[connection signal="exported" from="EditPaletteDialog" to="." method="_on_edit_palette_dialog_exported"]
[connection signal="saved" from="EditPaletteDialog" to="." method="_on_EditPaletteDialog_saved"] [connection signal="saved" from="EditPaletteDialog" to="." method="_on_EditPaletteDialog_saved"]
[connection signal="saved" from="CreatePaletteDialog" to="." method="_on_CreatePaletteDialog_saved"] [connection signal="saved" from="CreatePaletteDialog" to="." method="_on_CreatePaletteDialog_saved"]
[connection signal="color_changed" from="HiddenColorPickerButton" to="." method="_on_ColorPicker_color_changed"] [connection signal="color_changed" from="HiddenColorPickerButton" to="." method="_on_ColorPicker_color_changed"]

View file

@ -1,29 +1,22 @@
extends VBoxContainer extends VBoxContainer
var scroll := Vector2.ZERO var scroll := Vector2i.ZERO
var drag_started := false var drag_started := false
var drag_start_position := Vector2.ZERO var drag_start_position := Vector2i.ZERO
@onready var h_slider := %HScrollBar @onready var h_slider := %HScrollBar
@onready var v_slider := %VScrollBar @onready var v_slider := %VScrollBar
@onready var palette_grid := %PaletteGrid @onready var palette_grid := %PaletteGrid
@onready var scroll_container := %ScrollContainer
func _ready() -> void: func _input(event: InputEvent) -> void:
# Hide default scrollbars
scroll_container.get_h_scroll_bar().scale = Vector2.ZERO
scroll_container.get_v_scroll_bar().scale = Vector2.ZERO
func _input(event) -> void:
# Stops dragging even if middle mouse is released outside of this container # Stops dragging even if middle mouse is released outside of this container
if event is InputEventMouseButton: if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_MIDDLE and not event.pressed: if event.button_index == MOUSE_BUTTON_MIDDLE and not event.pressed:
drag_started = false drag_started = false
func set_sliders(palette: Palette, origin: Vector2) -> void: func set_sliders(palette: Palette, origin: Vector2i) -> void:
if not is_instance_valid(palette): if not is_instance_valid(palette):
return return
h_slider.value = origin.x h_slider.value = origin.x
@ -49,7 +42,7 @@ func scroll_grid() -> void:
palette_grid.scroll_palette(scroll) palette_grid.scroll_palette(scroll)
func _on_VSlider_value_changed(value) -> void: func _on_VSlider_value_changed(value: int) -> void:
scroll.y = value scroll.y = value
scroll_grid() scroll_grid()
@ -59,13 +52,13 @@ func _on_HSlider_value_changed(value: int) -> void:
scroll_grid() scroll_grid()
func _on_PaletteGrid_gui_input(event) -> void: func _on_PaletteGrid_gui_input(event: InputEvent) -> void:
if event is InputEventMouseButton: if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_MIDDLE and event.pressed: if event.button_index == MOUSE_BUTTON_MIDDLE and event.pressed:
drag_started = true drag_started = true
# Keeps position where the dragging started # Keeps position where the dragging started
drag_start_position = ( drag_start_position = (
event.position + Vector2(h_slider.value, v_slider.value) * palette_grid.swatch_size event.position + Vector2i(h_slider.value, v_slider.value) * palette_grid.swatch_size
) )
if event is InputEventMouseMotion and drag_started: if event is InputEventMouseMotion and drag_started:
@ -80,18 +73,18 @@ func _on_PaletteScroll_resized() -> void:
reset_sliders() reset_sliders()
func _on_PaletteScroll_gui_input(event) -> void: func _on_PaletteScroll_gui_input(event: InputEvent) -> void:
if event is InputEventMouseButton and event.pressed: if event is InputEventMouseButton and event.pressed:
var scroll_vector := Vector2.ZERO var scroll_vector := Vector2i.ZERO
if event.button_index == MOUSE_BUTTON_WHEEL_UP: if event.button_index == MOUSE_BUTTON_WHEEL_UP:
if event.ctrl_pressed: if event.ctrl_pressed:
palette_grid.change_swatch_size(Vector2.ONE) palette_grid.change_swatch_size(Vector2i.ONE)
else: else:
scroll_vector = Vector2.LEFT if event.shift_pressed else Vector2.UP scroll_vector = Vector2i.LEFT if event.shift_pressed else Vector2i.UP
if event.button_index == MOUSE_BUTTON_WHEEL_DOWN: if event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
if event.ctrl_pressed: if event.ctrl_pressed:
palette_grid.change_swatch_size(-Vector2.ONE) palette_grid.change_swatch_size(-Vector2i.ONE)
else: else:
scroll_vector = Vector2.RIGHT if event.shift_pressed else Vector2.DOWN scroll_vector = Vector2i.RIGHT if event.shift_pressed else Vector2i.DOWN
resize_grid() resize_grid()
set_sliders(palette_grid.current_palette, palette_grid.grid_window_origin + scroll_vector) set_sliders(palette_grid.current_palette, palette_grid.grid_window_origin + scroll_vector)

View file

@ -1,9 +1,9 @@
class_name PaletteSwatch class_name PaletteSwatch
extends ColorRect extends ColorRect
signal pressed(mouse_button) signal pressed(mouse_button: int)
signal double_clicked(mouse_button, position) signal double_clicked(mouse_button: int, position: Vector2)
signal dropped(source_index, new_index) signal dropped(source_index: int, new_index: int)
const DEFAULT_COLOR := Color(0.0, 0.0, 0.0, 0.0) const DEFAULT_COLOR := Color(0.0, 0.0, 0.0, 0.0)
@ -20,6 +20,12 @@ var empty := true:
mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
func _notification(what: int) -> void:
if what == NOTIFICATION_THEME_CHANGED:
if empty:
empty = true
func set_swatch_size(swatch_size: Vector2) -> void: func set_swatch_size(swatch_size: Vector2) -> void:
custom_minimum_size = swatch_size custom_minimum_size = swatch_size
size = swatch_size size = swatch_size
@ -55,7 +61,7 @@ func show_selected_highlight(new_value: bool, mouse_button: int) -> void:
queue_redraw() queue_redraw()
func _get_drag_data(_position: Vector2): func _get_drag_data(_position: Vector2) -> Variant:
var data = null var data = null
if not empty: if not empty:
var drag_icon: PaletteSwatch = self.duplicate() var drag_icon: PaletteSwatch = self.duplicate()

View file

@ -87,9 +87,6 @@ func change_theme(id: int) -> void:
for child in Global.preferences_dialog.get_node("Popups").get_children(): for child in Global.preferences_dialog.get_node("Popups").get_children():
child.theme = theme child.theme = theme
# Sets disabled theme color on palette swatches
Global.palette_panel.reset_empty_palette_swatches_color()
func change_clear_color() -> void: func change_clear_color() -> void:
var clear_color: Color = Global.control.theme.get_color("clear_color", "Misc") var clear_color: Color = Global.control.theme.get_color("clear_color", "Misc")

View file

@ -189,7 +189,7 @@ func _on_ImportPreviewDialog_confirmed() -> void:
OpenSave.import_reference_image_from_path(path) OpenSave.import_reference_image_from_path(path)
elif current_import_option == ImageImportOptions.PALETTE: elif current_import_option == ImageImportOptions.PALETTE:
Palettes.import_palette_from_path(path) Palettes.import_palette_from_path(path, true)
elif current_import_option == ImageImportOptions.BRUSH: elif current_import_option == ImageImportOptions.BRUSH:
add_brush() add_brush()

View file

@ -8,4 +8,4 @@ popup_window = true
ok_button_text = "Open" ok_button_text = "Open"
file_mode = 1 file_mode = 1
access = 2 access = 2
filters = PackedStringArray("*.pxo ; Pixelorama Project", "*.png ; PNG Image", "*.bmp ; BMP Image", "*.hdr ; Radiance HDR Image", "*.jpg,*.jpeg ; JPEG Image", "*.svg ; SVG Image", "*.tga ; TGA Image", "*.webp ; WebP Image", "*.tres; Pixelorama palette", "*.gpl; GIMP palette", "*pal; Palette") filters = PackedStringArray("*.pxo ; Pixelorama Project", "*.png ; PNG Image", "*.bmp ; BMP Image", "*.hdr ; Radiance HDR Image", "*.jpg,*.jpeg ; JPEG Image", "*.svg ; SVG Image", "*.tga ; TGA Image", "*.webp ; WebP Image", "*.json; Pixelorama palette", "*.gpl; GIMP palette", "*pal; Palette")