Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Palette import from GIMP .gpl, JASC .pal files! #329

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lorien/Assets/I18n/en.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ COLOR_PALETTE_PICKER_HINT_NEW Create new color palette
COLOR_PALETTE_PICKER_HINT_EDIT Edit the current color palette
COLOR_PALETTE_PICKER_HINT_DUPLICATE Duplicate the current color palette
COLOR_PALETTE_PICKER_HINT_DELETE Delete the current color palette permanently
COLOR_PALETTE_PICKER_HINT_IMPORT Import color palette from file...

# -----------------------------------------------------------------------------
# Statusbar strings
Expand Down Expand Up @@ -161,4 +162,4 @@ ACTION_duplicate_strokes Duplicate strokes
ACTION_toggle_zen_mode Toggle Zen Mode
ACTION_toggle_player Toggle Easteregg
ACTION_toggle_fullscreen Toggle Fullscreen
ACTION_canvas_pan_key Pan Key
ACTION_canvas_pan_key Pan Key
Binary file added lorien/Assets/Icons/import.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 34 additions & 0 deletions lorien/Assets/Icons/import.png.import
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[remap]

importer="texture"
type="CompressedTexture2D"
uid="uid://cy1dw232wfupq"
path="res://.godot/imported/import.png-d4f00b97279432a3c7140df130354f78.ctex"
metadata={
"vram_texture": false
}

[deps]

source_file="res://Assets/Icons/import.png"
dest_files=["res://.godot/imported/import.png-d4f00b97279432a3c7140df130354f78.ctex"]

[params]

compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
7 changes: 6 additions & 1 deletion lorien/Main.gd
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ extends Control
@onready var _delete_palette_window: Window = $DeletePaletteWindow
@onready var _edit_palette_window: Window = $EditPaletteWindow
@onready var _edit_palette_dialog: EditPaletteDialog = $EditPaletteWindow/EditPaletteDialog
@onready var _import_palette_dialog: FileDialog = $ImportPaletteDialog

var _last_input_time := 0
var _ui_visible := true
Expand All @@ -39,6 +40,7 @@ func _ready() -> void:
var docs_folder := OS.get_system_dir(OS.SYSTEM_DIR_DOCUMENTS)
_file_dialog.current_dir = Settings.get_value(Settings.GENERAL_DEFAULT_PROJECT_DIR, docs_folder)
_export_dialog.current_dir = Settings.get_value(Settings.GENERAL_DEFAULT_PROJECT_DIR, docs_folder)
_import_palette_dialog.current_dir = Settings.get_value(Settings.GENERAL_DEFAULT_PROJECT_DIR, docs_folder)

# Set tablet driver
var driver: String = Settings.get_value(Settings.GENERAL_TABLET_DRIVER, DisplayServer.tablet_get_current_driver())
Expand Down Expand Up @@ -274,6 +276,8 @@ func _is_mouse_on_ui() -> bool:
on_ui = on_ui || Utils.is_mouse_in_control(_toolbar)
on_ui = on_ui || Utils.is_mouse_in_control(_statusbar)
on_ui = on_ui || Utils.is_mouse_on_window(_file_dialog)
on_ui = on_ui || Utils.is_mouse_on_window(_export_dialog)
on_ui = on_ui || Utils.is_mouse_on_window(_import_palette_dialog)
on_ui = on_ui || Utils.is_mouse_on_window(_about_window)
on_ui = on_ui || Utils.is_mouse_on_window(_settings_window)
on_ui = on_ui || Utils.is_mouse_in_control(_brush_color_picker)
Expand All @@ -287,7 +291,8 @@ func is_dialog_open() -> bool:
return _about_window.visible || _settings_window.visible || \
_new_palette_window.visible || _edit_palette_window.visible || \
_delete_palette_window.visible || _file_dialog.visible || \
_unsaved_changes_window.visible || AlertDialog.visible
_import_palette_dialog.visible || AlertDialog.visible || \
_unsaved_changes_window.visible

# -------------------------------------------------------------------------------------------------
func _create_active_default_project() -> void:
Expand Down
13 changes: 13 additions & 0 deletions lorien/Main.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ add_new_palette_dialog_path = NodePath("../NewPaletteWindow/NewPaletteDialog")
edit_palette_dialog = NodePath("../EditPaletteWindow/EditPaletteDialog")
delete_palette_dialog = NodePath("../DeletePaletteWindow/DeletePaletteDialog")
toolbar_path = NodePath("../Topbar/Toolbar")
file_dialog_path = NodePath("../ImportPaletteDialog")

[node name="BackgroundColorPickerPopup" type="Popup" parent="."]
size = Vector2i(399, 525)
Expand All @@ -103,6 +104,7 @@ presets_visible = false

[node name="MainMenu" parent="." instance=ExtResource("5")]
visible = false
unfocusable = false
submenu_popup_delay = 0.1
file_dialog_path = NodePath("../FileDialog")

Expand Down Expand Up @@ -184,6 +186,17 @@ access = 2
filters = PackedStringArray("*.lorien")
use_native_dialog = true

[node name="ImportPaletteDialog" type="FileDialog" parent="."]
auto_translate_mode = 1
title = "Import Palette"
initial_position = 2
size = Vector2i(625, 175)
theme = ExtResource("8")
ok_button_text = "Import"
access = 2
filters = PackedStringArray("*.gpl;GIMP GPL", "*.pal;JASC PAL")
use_native_dialog = true

[node name="ExportDialog" type="FileDialog" parent="."]
initial_position = 2
size = Vector2i(625, 175)
Expand Down
8 changes: 6 additions & 2 deletions lorien/Palette/PaletteManager.gd
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func duplicate_palette(palette: Palette, new_palette_name: String) -> Palette:
var new_palette := Palette.new()
new_palette.name = new_palette_name
new_palette.builtin = false
new_palette.colors = palette.colors # TODO: make sure this is passed by-value
new_palette.colors = PackedColorArray(palette.colors)
palettes.append(new_palette)
_sort()

Expand All @@ -73,7 +73,11 @@ func remove_palette(palette: Palette) -> bool:
palettes.remove_at(index)
return true
return false


# -------------------------------------------------------------------------------------------------
func import_palette() -> void:
pass

# -------------------------------------------------------------------------------------------------
func set_active_palette_by_index(index: int) -> void:
if index < palettes.size():
Expand Down
104 changes: 104 additions & 0 deletions lorien/UI/ColorPalettePicker.gd
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ signal closed
@export var edit_palette_dialog: NodePath
@export var delete_palette_dialog: NodePath
@export var toolbar_path: NodePath
@export var file_dialog_path: NodePath

@onready var _toolbar: Toolbar = get_node(toolbar_path)
@onready var _palette_selection_button: OptionButton = $MarginContainer/VBoxContainer/Buttons/PaletteSelectionButton
Expand All @@ -21,6 +22,7 @@ signal closed
@onready var _new_button: TextureButton = $MarginContainer/VBoxContainer/Buttons/AddPaletteButton
@onready var _duplicate_button: TextureButton = $MarginContainer/VBoxContainer/Buttons/DuplicatePaletteButton
@onready var _delete_button: TextureButton = $MarginContainer/VBoxContainer/Buttons/DeletePaletteButton
@onready var _import_button: TextureButton = $MarginContainer/VBoxContainer/Buttons/ImportPaletteButton

var _active_palette_button: PaletteButton
var _active_color_index := -1
Expand All @@ -34,6 +36,7 @@ func _ready() -> void:
_edit_button.pressed.connect(_on_EditColorButton_pressed)
_duplicate_button.pressed.connect(_on_DuplicatePaletteButton_pressed)
_delete_button.pressed.connect(_on_DeletePaletteButton_pressed)
_import_button.pressed.connect(_on_ImportPaletteButton_pressed)

# -------------------------------------------------------------------------------------------------
func _input(event: InputEvent) -> void:
Expand Down Expand Up @@ -157,6 +160,107 @@ func _on_DeletePaletteButton_pressed() -> void:
var dialog: DeletePaletteDialog = get_node(delete_palette_dialog)
dialog.get_parent().popup_centered()

# -------------------------------------------------------------------------------------------------
func _on_ImportPaletteButton_pressed() -> void:
var file_dialog: FileDialog = get_node(file_dialog_path)
file_dialog.file_mode = FileDialog.FILE_MODE_OPEN_FILE
file_dialog.file_selected.connect(_on_palette_selected_to_import)
file_dialog.close_requested.connect(_on_file_dialog_closed)
file_dialog.invalidate()
file_dialog.popup_centered()

# -------------------------------------------------------------------------------------------------
func _on_palette_selected_to_import(filepath: String) -> void:
var palette : Palette
var palette_name: String
var palette_colors: PackedColorArray
var palette_string: String
var file := FileAccess.open(filepath, FileAccess.READ)
palette_string = file.get_as_text(true)
file.close()
match filepath.get_extension():
"gpl":
if !is_valid_gpl(palette_string):
return
palette_name = get_gpl_palette_name(palette_string)
if !palette_name:
palette_name = filepath.get_file().trim_suffix(".gpl")
palette_colors = parse_gpl_palette(palette_string)
"pal":
if !is_valid_pal(palette_string):
return
palette_name = filepath.get_file().trim_suffix(".pal")
palette_colors = parse_pal_palette(palette_string)
_:
return

palette = PaletteManager.create_custom_palette(palette_name)
if palette != null:
palette.colors = palette_colors
PaletteManager.save()
PaletteManager.set_active_palette(palette)
update_palettes()

# -------------------------------------------------------------------------------------------------
func is_valid_gpl(gpl_palette: String) -> bool:
return gpl_palette.begins_with("GIMP Palette")

# -------------------------------------------------------------------------------------------------
func get_gpl_palette_name(gpl_palette: String) -> String:
var name_line: String
name_line = gpl_palette.get_slice("\n", 1)
if name_line.begins_with("Name: "):
return name_line.right(-6).strip_edges()
else:
return ""

# -------------------------------------------------------------------------------------------------
func parse_gpl_palette(gpl_palette: String) -> PackedColorArray:
var color_array: PackedColorArray
for line in gpl_palette.split("\n"):
if !line or line.begins_with("#") or line == "GIMP Palette":
continue
var values: Array
if line.contains("\t"):
values = line.split("\t")
else:
values = line.split(" ")
color_array.append(
Color(
float(values[0])/255,
float(values[1])/255,
float(values[2])/255
)
)
return color_array

# -------------------------------------------------------------------------------------------------
func is_valid_pal(pal_palette: String) -> bool:
return pal_palette.begins_with("JASC-PAL")

# -------------------------------------------------------------------------------------------------
func parse_pal_palette(pal_palette: String) -> PackedColorArray:
var color_array: PackedColorArray
var n_colors: int
n_colors = int(pal_palette.split("\n")[2])
for i in range(3,n_colors+3):
var values: Array
values = pal_palette.split("\n")[i].split(" ")
color_array.append(
Color(
float(values[0])/255,
float(values[1])/255,
float(values[2])/255
)
)
return color_array

# -------------------------------------------------------------------------------------------------
func _on_file_dialog_closed() -> void:
var file_dialog: FileDialog = get_node(file_dialog_path)
Utils.remove_signal_connections(file_dialog, "file_selected")
Utils.remove_signal_connections(file_dialog, "close_requested")

# -------------------------------------------------------------------------------------------------
func toggle() -> void:
visible = !visible
Expand Down
12 changes: 11 additions & 1 deletion lorien/UI/ColorPalettePicker.tscn
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[gd_scene load_steps=11 format=3 uid="uid://dsxmmndtd4r2c"]
[gd_scene load_steps=12 format=3 uid="uid://dsxmmndtd4r2c"]

[ext_resource type="Theme" uid="uid://u5qnpgxqykiv" path="res://UI/Themes/theme_dark.tres" id="1"]
[ext_resource type="Script" path="res://UI/ColorPalettePicker.gd" id="2"]
Expand All @@ -7,6 +7,7 @@
[ext_resource type="Texture2D" uid="uid://ci340bpx1hg78" path="res://Assets/Icons/copy.png" id="5"]
[ext_resource type="Texture2D" uid="uid://c3maqrdnsjgiq" path="res://Assets/Icons/delete.png" id="6"]
[ext_resource type="Script" path="res://UI/Components/FlatTextureButton.gd" id="7"]
[ext_resource type="Texture2D" uid="uid://cy1dw232wfupq" path="res://Assets/Icons/import.png" id="7_yo14x"]

[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_eth5b"]
bg_color = Color(0.12549, 0.129412, 0.141176, 1)
Expand Down Expand Up @@ -81,6 +82,15 @@ script = ExtResource("7")
hover_tint = Color(0.662745, 0.945098, 0.87451, 1)
pressed_tint = Color(0.572549, 1, 0.894118, 1)

[node name="ImportPaletteButton" type="TextureButton" parent="MarginContainer/VBoxContainer/Buttons"]
layout_mode = 2
size_flags_vertical = 4
tooltip_text = "COLOR_PALETTE_PICKER_HINT_IMPORT"
texture_normal = ExtResource("7_yo14x")
script = ExtResource("7")
hover_tint = Color(0.662745, 0.945098, 0.87451, 1)
pressed_tint = Color(0.572549, 1, 0.894118, 1)

[node name="VSeparator" type="VSeparator" parent="MarginContainer/VBoxContainer/Buttons"]
layout_mode = 2
theme_override_styles/separator = SubResource("1")
Expand Down
5 changes: 2 additions & 3 deletions lorien/UI/Themes/theme_dark.tres
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
[gd_resource type="Theme" load_steps=27 format=4 uid="uid://u5qnpgxqykiv"]
[gd_resource type="Theme" load_steps=26 format=4 uid="uid://u5qnpgxqykiv"]

[ext_resource type="Texture2D" uid="uid://bp1yka17gbjtu" path="res://Assets/Icons/close.png" id="1_qgxa7"]
[ext_resource type="StyleBox" uid="uid://kdduww61cjw" path="res://UI/Themes/tab_inactive_dark.tres" id="2_n6mkw"]
[ext_resource type="StyleBox" uid="uid://dtn7ehcyfik4a" path="res://UI/Themes/tab_active_dark.tres" id="3_rqnin"]

Expand Down Expand Up @@ -2562,7 +2561,7 @@ TabBar/constants/h_separation = 4
TabBar/constants/icon_max_width = 0
TabBar/constants/outline_size = 0
TabBar/fonts/font = SubResource("FontFile_1bm21")
TabBar/icons/close = ExtResource("1_qgxa7")
TabBar/icons/close = null
TabBar/styles/button_highlight = SubResource("StyleBoxEmpty_me351")
TabBar/styles/button_pressed = SubResource("StyleBoxEmpty_n0chp")
TabBar/styles/tab_disabled = ExtResource("2_n6mkw")
Expand Down