Merge pull request #197 from sapient-cogbag/xdg-standard
XDG basedir standard on X11 Godot platforms
14
Main.tscn
|
@ -1174,8 +1174,8 @@ resizable = true
|
||||||
mode = 0
|
mode = 0
|
||||||
access = 2
|
access = 2
|
||||||
filters = PoolStringArray( "*.pxo ; Pixelorama Project" )
|
filters = PoolStringArray( "*.pxo ; Pixelorama Project" )
|
||||||
current_dir = "C:/Users/Overloaded/Dropbox/Orama Founding Members/εταιρικα αρχεια/Godot Projects/Pixelorama"
|
current_dir = ""
|
||||||
current_path = "C:/Users/Overloaded/Dropbox/Orama Founding Members/εταιρικα αρχεια/Godot Projects/Pixelorama/"
|
current_path = ""
|
||||||
|
|
||||||
[node name="SaveSprite" type="FileDialog" parent="."]
|
[node name="SaveSprite" type="FileDialog" parent="."]
|
||||||
anchor_left = 0.5
|
anchor_left = 0.5
|
||||||
|
@ -1190,10 +1190,12 @@ window_title = "Save Sprite as .pxo"
|
||||||
resizable = true
|
resizable = true
|
||||||
access = 2
|
access = 2
|
||||||
filters = PoolStringArray( "*.pxo ; Pixelorama Project" )
|
filters = PoolStringArray( "*.pxo ; Pixelorama Project" )
|
||||||
current_dir = "C:/Users/Overloaded/Dropbox/Orama Founding Members/εταιρικα αρχεια/Godot Projects/Pixelorama"
|
current_dir = ""
|
||||||
current_path = "C:/Users/Overloaded/Dropbox/Orama Founding Members/εταιρικα αρχεια/Godot Projects/Pixelorama/"
|
current_path = ""
|
||||||
|
|
||||||
[node name="ImportSprites" parent="." instance=ExtResource( 29 )]
|
[node name="ImportSprites" parent="." instance=ExtResource( 29 )]
|
||||||
|
current_dir = ""
|
||||||
|
current_path = ""
|
||||||
|
|
||||||
[node name="ExportDialog" parent="." instance=ExtResource( 39 )]
|
[node name="ExportDialog" parent="." instance=ExtResource( 39 )]
|
||||||
|
|
||||||
|
@ -1242,8 +1244,8 @@ dialog_text = "This is an error message!"
|
||||||
|
|
||||||
[node name="PaletteImportFileDialog" parent="." instance=ExtResource( 37 )]
|
[node name="PaletteImportFileDialog" parent="." instance=ExtResource( 37 )]
|
||||||
filters = PoolStringArray( "*.json ; JavaScript Object Notation", "*.gpl ; Gimp Palette Library", "*.png; Portable Network Graphics" )
|
filters = PoolStringArray( "*.json ; JavaScript Object Notation", "*.gpl ; Gimp Palette Library", "*.png; Portable Network Graphics" )
|
||||||
current_dir = "C:/Users/Overloaded/Dropbox/Orama Founding Members/εταιρικα αρχεια/Godot Projects/Pixelorama"
|
current_dir = ""
|
||||||
current_path = "C:/Users/Overloaded/Dropbox/Orama Founding Members/εταιρικα αρχεια/Godot Projects/Pixelorama/"
|
current_path = ""
|
||||||
|
|
||||||
[node name="LeftCursor" type="Sprite" parent="."]
|
[node name="LeftCursor" type="Sprite" parent="."]
|
||||||
visible = false
|
visible = false
|
||||||
|
|
|
@ -7,6 +7,9 @@ enum Brush_Types {PIXEL, CIRCLE, FILLED_CIRCLE, FILE, RANDOM_FILE, CUSTOM}
|
||||||
var root_directory := "."
|
var root_directory := "."
|
||||||
var window_title := "" setget title_changed # Why doesn't Godot have get_window_title()?
|
var window_title := "" setget title_changed # Why doesn't Godot have get_window_title()?
|
||||||
var config_cache := ConfigFile.new()
|
var config_cache := ConfigFile.new()
|
||||||
|
var XDGDataPaths = preload("res://Scripts/XDGDataPaths.gd")
|
||||||
|
var directory_module : Node
|
||||||
|
|
||||||
# warning-ignore:unused_class_variable
|
# warning-ignore:unused_class_variable
|
||||||
var loaded_locales : Array
|
var loaded_locales : Array
|
||||||
var undo_redo : UndoRedo
|
var undo_redo : UndoRedo
|
||||||
|
@ -263,12 +266,16 @@ func _ready() -> void:
|
||||||
root_directory = OS.get_executable_path().get_base_dir()
|
root_directory = OS.get_executable_path().get_base_dir()
|
||||||
# Load settings from the config file
|
# Load settings from the config file
|
||||||
config_cache.load("user://cache.ini")
|
config_cache.load("user://cache.ini")
|
||||||
|
|
||||||
|
# The fact that root_dir is set earlier than this is important
|
||||||
|
# XDGDataDirs depends on it nyaa
|
||||||
|
directory_module = XDGDataPaths.new()
|
||||||
|
|
||||||
undo_redo = UndoRedo.new()
|
undo_redo = UndoRedo.new()
|
||||||
transparent_background = ImageTexture.new()
|
transparent_background = ImageTexture.new()
|
||||||
transparent_background.create_from_image(preload("res://Assets/Graphics/Canvas Backgrounds/Transparent Background Dark.png"), 0)
|
transparent_background.create_from_image(preload("res://Assets/Graphics/Canvas Backgrounds/Transparent Background Dark.png"), 0)
|
||||||
image_clipboard = Image.new()
|
image_clipboard = Image.new()
|
||||||
|
|
||||||
var root = get_tree().get_root()
|
var root = get_tree().get_root()
|
||||||
control = find_node_by_name(root, "Control")
|
control = find_node_by_name(root, "Control")
|
||||||
top_menu_container = find_node_by_name(control, "TopMenuContainer")
|
top_menu_container = find_node_by_name(control, "TopMenuContainer")
|
||||||
|
|
|
@ -1,17 +1,224 @@
|
||||||
extends Node
|
extends Node
|
||||||
|
|
||||||
func import_brushes(path : String) -> void:
|
# Get hold of the brushes, including random brushes (subdirectories and % files
|
||||||
var brushes_dir := Directory.new()
|
# in them, non % files get loaded independently.) nyaaa
|
||||||
brushes_dir.open(Global.root_directory)
|
# Returns a list of [
|
||||||
if !brushes_dir.dir_exists(path):
|
# [non random single png files in the root subdir],
|
||||||
brushes_dir.make_dir(path)
|
# {
|
||||||
|
# map of subdirectories to lists of files for
|
||||||
|
# the randomised brush - if a directory contains no
|
||||||
|
# randomised files then it is not included in this.
|
||||||
|
# },
|
||||||
|
# {
|
||||||
|
# map of subdirectories to lists of files inside of them
|
||||||
|
# that are not for randomised brushes.
|
||||||
|
# }
|
||||||
|
# ]
|
||||||
|
# The separation of nonrandomised and randomised files
|
||||||
|
# in subdirectories allows different XDG_DATA_DIR overriding
|
||||||
|
# for each nyaa.
|
||||||
|
#
|
||||||
|
# Returns null if the directory gave an error opening.
|
||||||
|
#
|
||||||
|
func get_brush_files_from_directory(directory: String): # -> Array
|
||||||
|
var base_png_files := [] # list of files in the base directory
|
||||||
|
var subdirectories := [] # list of subdirectories to process.
|
||||||
|
|
||||||
|
var randomised_subdir_files_map : Dictionary = {}
|
||||||
|
var nonrandomised_subdir_files_map : Dictionary = {}
|
||||||
|
|
||||||
|
var main_directory : Directory = Directory.new()
|
||||||
|
var err := main_directory.open(directory)
|
||||||
|
if err != OK:
|
||||||
|
return null
|
||||||
|
|
||||||
|
|
||||||
|
# Build first the list of base png files and all subdirectories to
|
||||||
|
# scan later (skip navigational . and ..)
|
||||||
|
main_directory.list_dir_begin(true)
|
||||||
|
var fname : String = main_directory.get_next()
|
||||||
|
while fname != "":
|
||||||
|
if main_directory.current_is_dir():
|
||||||
|
subdirectories.append(fname)
|
||||||
|
else: # Filter for pngs
|
||||||
|
if fname.get_extension().to_lower() == "png":
|
||||||
|
print_debug("Found brush at '%s'" % [fname])
|
||||||
|
base_png_files.append(fname)
|
||||||
|
|
||||||
|
# go to next
|
||||||
|
fname = main_directory.get_next()
|
||||||
|
main_directory.list_dir_end()
|
||||||
|
|
||||||
|
# Now we iterate over subdirectories!
|
||||||
|
for subdirectory in subdirectories:
|
||||||
|
var the_directory : Directory = Directory.new()
|
||||||
|
|
||||||
|
# Holds names of files that make this
|
||||||
|
# a component of a randomised brush ^.^
|
||||||
|
var randomised_files := []
|
||||||
|
|
||||||
|
# Non-randomise-indicated image files
|
||||||
|
var non_randomised_files := []
|
||||||
|
|
||||||
|
the_directory.open(directory.plus_file(subdirectory))
|
||||||
|
the_directory.list_dir_begin(true)
|
||||||
|
var curr_file := the_directory.get_next()
|
||||||
|
|
||||||
|
while curr_file != "":
|
||||||
|
# only do stuff if we are actually dealing with a file
|
||||||
|
# and png one at that nya
|
||||||
|
if !the_directory.current_is_dir() and curr_file.get_extension().to_lower() == "png":
|
||||||
|
# if we are a random element, add
|
||||||
|
if "%" in curr_file:
|
||||||
|
randomised_files.append(curr_file)
|
||||||
|
else:
|
||||||
|
non_randomised_files.append(curr_file)
|
||||||
|
curr_file = the_directory.get_next()
|
||||||
|
|
||||||
|
the_directory.list_dir_end()
|
||||||
|
|
||||||
|
# Add these to the maps nyaa
|
||||||
|
if len(randomised_files) > 0:
|
||||||
|
randomised_subdir_files_map[subdirectory] = randomised_files
|
||||||
|
if len(non_randomised_files) > 0:
|
||||||
|
nonrandomised_subdir_files_map[subdirectory] = non_randomised_files
|
||||||
|
# We are done generating the maps!
|
||||||
|
return [base_png_files, randomised_subdir_files_map, nonrandomised_subdir_files_map]
|
||||||
|
|
||||||
|
|
||||||
|
# Add a randomised brush from the given list of files as a
|
||||||
|
# source.
|
||||||
|
# The tooltip name is what shows up on the tooltip
|
||||||
|
# and is probably in this case the name of the containing
|
||||||
|
# randomised directory.
|
||||||
|
func add_randomised_brush(fpaths : Array, tooltip_name : String) -> void:
|
||||||
|
# Attempt to load the images from the file paths.
|
||||||
|
var loaded_images : Array = []
|
||||||
|
for filen in fpaths:
|
||||||
|
var image := Image.new()
|
||||||
|
var err := image.load(filen)
|
||||||
|
if err == OK:
|
||||||
|
image.convert(Image.FORMAT_RGBA8)
|
||||||
|
loaded_images.append(image)
|
||||||
|
print_debug("Loaded image from '%s'" % [filen])
|
||||||
|
|
||||||
|
# If any images were successfully loaded, then
|
||||||
|
# we create the randomised brush button, copied
|
||||||
|
# from find_brushes.
|
||||||
|
|
||||||
|
if len(loaded_images) > 0: # actually have images
|
||||||
|
# to use.
|
||||||
|
# take initial image...
|
||||||
|
var first_image : Image = loaded_images.pop_front()
|
||||||
|
|
||||||
|
# The index which this random brush will be at
|
||||||
|
var next_random_brush_index := Global.file_brush_container.get_child_count()
|
||||||
|
|
||||||
|
Global.custom_brushes.append(first_image)
|
||||||
|
Global.create_brush_button(first_image, Global.Brush_Types.RANDOM_FILE, tooltip_name)
|
||||||
|
# # Process the rest
|
||||||
|
for remaining_image in loaded_images:
|
||||||
|
var brush_button = Global.file_brush_container.get_child(next_random_brush_index)
|
||||||
|
brush_button.random_brushes.append(remaining_image)
|
||||||
|
|
||||||
|
# Add a plain brush from the given path to the list of brushes.
|
||||||
|
# Taken, again, from find_brushes
|
||||||
|
func add_plain_brush(path: String, tooltip_name: String) -> void:
|
||||||
|
var image := Image.new()
|
||||||
|
var err := image.load(path)
|
||||||
|
if err != OK:
|
||||||
|
return
|
||||||
|
# do the standard conversion thing...
|
||||||
|
image.convert(Image.FORMAT_RGBA8)
|
||||||
|
Global.custom_brushes.append(image)
|
||||||
|
Global.create_brush_button(image, Global.Brush_Types.FILE, tooltip_name)
|
||||||
|
|
||||||
|
|
||||||
|
# Import brushes, in priority order, from the paths in question in priority order
|
||||||
|
# i.e. with an override system
|
||||||
|
# We use a very particular override system here where, for randomised brushes
|
||||||
|
# the directories containing them get overridden, but for nonrandomised files
|
||||||
|
# (including in directories containing randomised components too), the override
|
||||||
|
# is on a file-by-file basis nyaaaa ^.^
|
||||||
|
func import_brushes(priority_ordered_search_path: Array) -> void:
|
||||||
|
# Maps for files in the base directory (name : true)
|
||||||
|
var processed_basedir_paths : Dictionary = {}
|
||||||
|
var randomised_brush_subdirectories : Dictionary = {}
|
||||||
|
# Map from a subdirectory to a map similar to processed_basedir_files
|
||||||
|
# i.e. once a filename has been dealt with, set it to true.
|
||||||
|
var processed_subdir_paths : Dictionary = {}
|
||||||
|
|
||||||
|
# Sets of results of get_brush_files_from_directory
|
||||||
|
var all_available_paths : Array = []
|
||||||
|
for directory in priority_ordered_search_path:
|
||||||
|
all_available_paths.append(get_brush_files_from_directory(directory))
|
||||||
|
|
||||||
|
# Now to process. Note these are in order of the
|
||||||
|
# priority, as intended nyaa :)
|
||||||
|
for i in range(len(all_available_paths)):
|
||||||
|
var available_brush_file_information = all_available_paths[i]
|
||||||
|
var current_main_directory: String = priority_ordered_search_path[i]
|
||||||
|
if available_brush_file_information != null:
|
||||||
|
# The brush files in the main directory
|
||||||
|
var main_directory_file_paths : Array = available_brush_file_information[0]
|
||||||
|
# The subdirectory/list-of-randomised-brush-files
|
||||||
|
# map for this directory
|
||||||
|
var randomised_brush_subdirectory_map : Dictionary = available_brush_file_information[1]
|
||||||
|
# Map for subdirectories to non-randomised-brush files nyaa
|
||||||
|
var nonrandomised_brush_subdirectory_map : Dictionary = available_brush_file_information[2]
|
||||||
|
|
||||||
|
# Iterate over components and do stuff with them! nyaa
|
||||||
|
# first for the main directory path...
|
||||||
|
for subfile in main_directory_file_paths:
|
||||||
|
if not (subfile in processed_basedir_paths):
|
||||||
|
add_plain_brush(
|
||||||
|
current_main_directory.plus_file(subfile),
|
||||||
|
subfile.get_basename()
|
||||||
|
)
|
||||||
|
processed_basedir_paths[subfile] = true
|
||||||
|
|
||||||
|
# Iterate over the randomised brush files nyaa
|
||||||
|
for randomised_subdir in randomised_brush_subdirectory_map:
|
||||||
|
if not (randomised_subdir in randomised_brush_subdirectories):
|
||||||
|
var full_paths := []
|
||||||
|
# glue the proper path onto the single file names in the
|
||||||
|
# random brush directory data system, so they can be
|
||||||
|
# opened nya
|
||||||
|
for non_extended_path in randomised_brush_subdirectory_map[randomised_subdir]:
|
||||||
|
full_paths.append(current_main_directory.plus_file(
|
||||||
|
randomised_subdir
|
||||||
|
).plus_file(
|
||||||
|
non_extended_path
|
||||||
|
))
|
||||||
|
# Now load!
|
||||||
|
add_randomised_brush(full_paths, randomised_subdir)
|
||||||
|
# and mark that we are done in the overall map ^.^
|
||||||
|
randomised_brush_subdirectories[randomised_subdir] = true
|
||||||
|
# Now to iterate over the nonrandom brush files inside directories
|
||||||
|
for nonrandomised_subdir in nonrandomised_brush_subdirectory_map:
|
||||||
|
# initialise the set-map for this one if not already present :)
|
||||||
|
if not (nonrandomised_subdir in processed_subdir_paths):
|
||||||
|
processed_subdir_paths[nonrandomised_subdir] = {}
|
||||||
|
# Get the paths within this subdirectory to check if they are
|
||||||
|
# processed or not and if not, then process them.
|
||||||
|
var relpaths_of_contained_nonrandom_brushes : Array = nonrandomised_brush_subdirectory_map[nonrandomised_subdir]
|
||||||
|
for relative_path in relpaths_of_contained_nonrandom_brushes:
|
||||||
|
if not (relative_path in processed_subdir_paths[nonrandomised_subdir]):
|
||||||
|
# We are not yet processed
|
||||||
|
var full_path : String = current_main_directory.plus_file(
|
||||||
|
nonrandomised_subdir
|
||||||
|
).plus_file(
|
||||||
|
relative_path
|
||||||
|
)
|
||||||
|
# Add the path with the tooltip including the directory
|
||||||
|
add_plain_brush(full_path, nonrandomised_subdir.plus_file(
|
||||||
|
relative_path
|
||||||
|
).get_basename())
|
||||||
|
# Mark this as a processed relpath
|
||||||
|
processed_subdir_paths[nonrandomised_subdir][relative_path] = true
|
||||||
|
|
||||||
|
|
||||||
var subdirectories := find_brushes(brushes_dir, path)
|
|
||||||
for subdir_str in subdirectories:
|
|
||||||
var subdir := Directory.new()
|
|
||||||
find_brushes(subdir, "%s/%s" % [path, subdir_str])
|
|
||||||
|
|
||||||
Global.brushes_from_files = Global.custom_brushes.size()
|
|
||||||
|
|
||||||
func find_brushes(brushes_dir : Directory, path : String) -> Array:
|
func find_brushes(brushes_dir : Directory, path : String) -> Array:
|
||||||
var subdirectories := []
|
var subdirectories := []
|
||||||
|
|
|
@ -168,7 +168,7 @@ func _ready() -> void:
|
||||||
Global.layers_container.get_child(0).label.text = Global.layers[0][0]
|
Global.layers_container.get_child(0).label.text = Global.layers[0][0]
|
||||||
Global.layers_container.get_child(0).line_edit.text = Global.layers[0][0]
|
Global.layers_container.get_child(0).line_edit.text = Global.layers[0][0]
|
||||||
|
|
||||||
Import.import_brushes("Brushes")
|
Import.import_brushes(Global.directory_module.get_brushes_search_path_in_order())
|
||||||
|
|
||||||
Global.left_color_picker.get_picker().presets_visible = false
|
Global.left_color_picker.get_picker().presets_visible = false
|
||||||
Global.right_color_picker.get_picker().presets_visible = false
|
Global.right_color_picker.get_picker().presets_visible = false
|
||||||
|
|
|
@ -106,12 +106,31 @@ func re_index_swatches() -> void:
|
||||||
child.index = index
|
child.index = index
|
||||||
index += 1
|
index += 1
|
||||||
|
|
||||||
|
# Rename a palette, copying to user directory if necessary.
|
||||||
|
func rename_palette_file_with_priority_dirs(old_fname: String, new_fname: String) -> void:
|
||||||
|
var user_write_directory: String = Global.directory_module.get_palette_write_path()
|
||||||
|
var usrwrite_dir := Directory.new()
|
||||||
|
usrwrite_dir.open(user_write_directory)
|
||||||
|
if usrwrite_dir.file_exists(old_fname):
|
||||||
|
usrwrite_dir.rename(old_fname, new_fname)
|
||||||
|
else:
|
||||||
|
# Scan through the main system directories
|
||||||
|
var priority_dirs : Array = Global.directory_module.get_palette_search_path_in_order()
|
||||||
|
var best_clone_location = Global.palette_container.get_best_palette_file_location(
|
||||||
|
priority_dirs,
|
||||||
|
old_fname
|
||||||
|
)
|
||||||
|
if best_clone_location != null:
|
||||||
|
usrwrite_dir.copy(best_clone_location, new_fname)
|
||||||
|
|
||||||
|
|
||||||
func _on_EditPaletteSaveButton_pressed() -> void:
|
func _on_EditPaletteSaveButton_pressed() -> void:
|
||||||
if palette_name_edit.text != current_palette:
|
if palette_name_edit.text != current_palette:
|
||||||
Global.palettes.erase(current_palette)
|
Global.palettes.erase(current_palette)
|
||||||
var dir := Directory.new()
|
rename_palette_file_with_priority_dirs(
|
||||||
dir.open(Global.root_directory)
|
current_palette + ".json",
|
||||||
dir.rename("Palettes".plus_file(current_palette + ".json"), "Palettes".plus_file(palette_name_edit.text + ".json"))
|
palette_name_edit.text + ".json"
|
||||||
|
)
|
||||||
current_palette = palette_name_edit.text
|
current_palette = palette_name_edit.text
|
||||||
working_palette.name = current_palette
|
working_palette.name = current_palette
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ extends GridContainer
|
||||||
|
|
||||||
const palette_button = preload("res://Prefabs/PaletteButton.tscn")
|
const palette_button = preload("res://Prefabs/PaletteButton.tscn")
|
||||||
|
|
||||||
|
|
||||||
var palettes_path := "Palettes"
|
var palettes_path := "Palettes"
|
||||||
var current_palette = "Default"
|
var current_palette = "Default"
|
||||||
var from_palette : Palette
|
var from_palette : Palette
|
||||||
|
@ -154,30 +155,38 @@ func on_color_select(index : int) -> void:
|
||||||
Global.update_right_custom_brush()
|
Global.update_right_custom_brush()
|
||||||
|
|
||||||
func _load_palettes() -> void:
|
func _load_palettes() -> void:
|
||||||
palettes_path = Global.root_directory.plus_file("Palettes")
|
Global.directory_module.ensure_xdg_user_dirs_exist()
|
||||||
var dir := Directory.new()
|
var search_locations = Global.directory_module.get_palette_search_path_in_order()
|
||||||
dir.open(Global.root_directory)
|
var priority_ordered_files := get_palette_priority_file_map(search_locations)
|
||||||
if not dir.dir_exists(palettes_path):
|
|
||||||
dir.make_dir(palettes_path)
|
# Iterate backwards, so any palettes defined in default files
|
||||||
|
# get overwritten by those of the same name in user files
|
||||||
var palette_files : Array = get_palette_files(palettes_path)
|
search_locations.invert()
|
||||||
|
priority_ordered_files.invert()
|
||||||
for file_name in palette_files:
|
for i in range(len(search_locations)):
|
||||||
var palette : Palette = Palette.new().load_from_file(palettes_path.plus_file(file_name))
|
var base_directory : String = search_locations[i]
|
||||||
if palette:
|
var palette_files : Array = priority_ordered_files[i]
|
||||||
Global.palettes[palette.name] = palette
|
for file_name in palette_files:
|
||||||
Global.palette_option_button.add_item(palette.name)
|
var palette : Palette = Palette.new().load_from_file(base_directory.plus_file(file_name))
|
||||||
var index: int = Global.palette_option_button.get_item_count() - 1
|
if palette:
|
||||||
Global.palette_option_button.set_item_metadata(index, palette.name)
|
Global.palettes[palette.name] = palette
|
||||||
if palette.name == "Default":
|
Global.palette_option_button.add_item(palette.name)
|
||||||
Global.palette_option_button.select(index)
|
var index: int = Global.palette_option_button.get_item_count() - 1
|
||||||
|
Global.palette_option_button.set_item_metadata(index, palette.name)
|
||||||
|
if palette.name == "Default":
|
||||||
|
Global.palette_option_button.select(index)
|
||||||
|
|
||||||
if not "Default" in Global.palettes && Global.palettes.size() > 0:
|
if not "Default" in Global.palettes && Global.palettes.size() > 0:
|
||||||
Global.control._on_PaletteOptionButton_item_selected(0)
|
Global.palette_container._on_PaletteOptionButton_item_selected(0)
|
||||||
|
|
||||||
func get_palette_files(path : String) -> Array:
|
# Get the palette files in a single directory.
|
||||||
|
# if it does not exist, return []
|
||||||
|
func get_palette_files(path : String ) -> Array:
|
||||||
var dir := Directory.new()
|
var dir := Directory.new()
|
||||||
var results = []
|
var results = []
|
||||||
|
|
||||||
|
if not dir.dir_exists(path):
|
||||||
|
return []
|
||||||
|
|
||||||
dir.open(path)
|
dir.open(path)
|
||||||
dir.list_dir_begin()
|
dir.list_dir_begin()
|
||||||
|
@ -186,15 +195,59 @@ func get_palette_files(path : String) -> Array:
|
||||||
var file_name = dir.get_next()
|
var file_name = dir.get_next()
|
||||||
if file_name == "":
|
if file_name == "":
|
||||||
break
|
break
|
||||||
elif not file_name.begins_with(".") && file_name.to_lower().ends_with("json"):
|
elif (not file_name.begins_with(".")) && file_name.to_lower().ends_with("json") && not dir.current_is_dir():
|
||||||
results.append(file_name)
|
results.append(file_name)
|
||||||
|
|
||||||
dir.list_dir_end()
|
dir.list_dir_end()
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
# This returns an array of arrays, with priorities.
|
||||||
|
# In particular, it takes an array of paths to look for
|
||||||
|
# arrays in, in order of file and palette override priority
|
||||||
|
# such that the files in the first directory override the
|
||||||
|
# second, third, etc. ^.^
|
||||||
|
# It returns an array of arrays, where each output array
|
||||||
|
# corresponds to the given input array at the same index, and
|
||||||
|
# contains the (relative to the given directory) palette files
|
||||||
|
# to load, excluding all ones already existing in higher-priority
|
||||||
|
# directories. nya
|
||||||
|
# in particular, this also means you can run backwards on the result
|
||||||
|
# so that palettes with the given palette name in the higher priority
|
||||||
|
# directories override those set in lower priority directories :)
|
||||||
|
func get_palette_priority_file_map(looking_paths: Array) -> Array:
|
||||||
|
var final_list := []
|
||||||
|
# Holds pattern files already found
|
||||||
|
var working_file_set : Dictionary = {}
|
||||||
|
for search_directory in looking_paths:
|
||||||
|
var to_add_files := []
|
||||||
|
var files = get_palette_files(search_directory)
|
||||||
|
# files to check
|
||||||
|
for maybe_to_add in files:
|
||||||
|
if not maybe_to_add in working_file_set:
|
||||||
|
to_add_files.append(maybe_to_add)
|
||||||
|
working_file_set[maybe_to_add] = true
|
||||||
|
|
||||||
|
final_list.append(to_add_files)
|
||||||
|
return final_list
|
||||||
|
|
||||||
|
# Locate the highest priority palette by the given relative filename
|
||||||
|
# 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(len(looking_paths)):
|
||||||
|
var base_path : String = looking_paths[i]
|
||||||
|
var the_files : Array = priority_fmap[i]
|
||||||
|
if the_files.has(fname):
|
||||||
|
return base_path.plus_file(fname)
|
||||||
|
|
||||||
|
return null
|
||||||
|
|
||||||
func save_palette(palette_name : String, filename : String) -> void:
|
func save_palette(palette_name : String, filename : String) -> void:
|
||||||
|
Global.directory_module.ensure_xdg_user_dirs_exist()
|
||||||
var palette = Global.palettes[palette_name]
|
var palette = Global.palettes[palette_name]
|
||||||
palette.save_to_file(palettes_path.plus_file(filename))
|
var palettes_write_path: String = Global.directory_module.get_palette_write_path()
|
||||||
|
palette.save_to_file(palettes_write_path.plus_file(filename))
|
||||||
|
|
||||||
|
|
||||||
func _on_NewPaletteDialog_popup_hide() -> void:
|
func _on_NewPaletteDialog_popup_hide() -> void:
|
||||||
|
|
135
Scripts/XDGDataPaths.gd
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
# These are *with* the config subdirectory name
|
||||||
|
var xdg_data_home : String
|
||||||
|
var xdg_data_dirs : Array
|
||||||
|
|
||||||
|
# These are *without* the config subdirectory name
|
||||||
|
var raw_xdg_data_home : String
|
||||||
|
var raw_xdg_data_dirs : Array
|
||||||
|
|
||||||
|
# Default location for xdg_data_home relative to $HOME
|
||||||
|
const default_xdg_data_home_rel := ".local/share"
|
||||||
|
const default_xdg_data_dirs := ["/usr/local/share", "/usr/share"]
|
||||||
|
|
||||||
|
const config_subdir_name := "pixelorama"
|
||||||
|
|
||||||
|
const palettes_data_subdirectory := "Palettes"
|
||||||
|
const brushes_data_subdirectory := "Brushes"
|
||||||
|
|
||||||
|
# Declare member variables here. Examples:
|
||||||
|
# var a = 2
|
||||||
|
# var b = "text"
|
||||||
|
|
||||||
|
|
||||||
|
# Get if we should use XDG standard or not nyaaaa
|
||||||
|
func use_xdg_standard() -> bool:
|
||||||
|
# see: https://docs.godotengine.org/en/latest/getting_started/workflow/export/feature_tags.html
|
||||||
|
# return OS.has_feature("Linux") or OS.has_feature("BSD")
|
||||||
|
# Previous was unreliable and buggy >.< nyaa
|
||||||
|
return OS.get_name() == "X11"
|
||||||
|
|
||||||
|
# Called when the node enters the scene tree for the first time.
|
||||||
|
func _ready():
|
||||||
|
pass
|
||||||
|
|
||||||
|
func _init():
|
||||||
|
if use_xdg_standard():
|
||||||
|
print("Detected system where we should use XDG basedir standard (currently Linux or BSD)")
|
||||||
|
var home := OS.get_environment("HOME")
|
||||||
|
raw_xdg_data_home = home.plus_file(
|
||||||
|
default_xdg_data_home_rel
|
||||||
|
)
|
||||||
|
xdg_data_home = raw_xdg_data_home.plus_file(
|
||||||
|
config_subdir_name
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create defaults
|
||||||
|
xdg_data_dirs = []
|
||||||
|
raw_xdg_data_dirs = default_xdg_data_dirs
|
||||||
|
for default_loc in raw_xdg_data_dirs:
|
||||||
|
xdg_data_dirs.append(
|
||||||
|
default_loc.plus_file(config_subdir_name)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Now check the XDG environment variables and if
|
||||||
|
# present, replace the defaults with them!
|
||||||
|
# See: https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||||
|
# Checks the xdg data home var
|
||||||
|
if OS.has_environment("XDG_DATA_HOME"):
|
||||||
|
raw_xdg_data_home = OS.get_environment("XDG_DATA_HOME")
|
||||||
|
xdg_data_home = raw_xdg_data_home.plus_file(config_subdir_name)
|
||||||
|
# Checks the list of files var, and processes them.
|
||||||
|
if OS.has_environment("XDG_DATA_DIRS"):
|
||||||
|
var raw_env_var := OS.get_environment("XDG_DATA_DIRS")
|
||||||
|
# includes empties.
|
||||||
|
var unappended_subdirs := raw_env_var.split(":", true)
|
||||||
|
raw_xdg_data_dirs = unappended_subdirs
|
||||||
|
xdg_data_dirs = []
|
||||||
|
for unapp_subdir in raw_xdg_data_dirs:
|
||||||
|
xdg_data_dirs.append(unapp_subdir.plus_file(config_subdir_name))
|
||||||
|
|
||||||
|
else:
|
||||||
|
raw_xdg_data_home = Global.root_directory
|
||||||
|
xdg_data_home = raw_xdg_data_home.plus_file(config_subdir_name)
|
||||||
|
raw_xdg_data_dirs = []
|
||||||
|
xdg_data_dirs = []
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func append_file_to_all(basepaths: Array, subpath: String) -> Array:
|
||||||
|
var res := []
|
||||||
|
for _path in basepaths:
|
||||||
|
res.append(_path.plus_file(subpath))
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
# Get search paths in order of priority
|
||||||
|
func get_search_paths_in_order() -> Array:
|
||||||
|
return [xdg_data_home] + xdg_data_dirs
|
||||||
|
|
||||||
|
# Gets the paths, in order of search priority, for palettes.
|
||||||
|
func get_palette_search_path_in_order() -> Array:
|
||||||
|
var base_paths := get_search_paths_in_order()
|
||||||
|
return append_file_to_all(base_paths, palettes_data_subdirectory)
|
||||||
|
|
||||||
|
# Gets the paths, in order of search priority, for brushes.
|
||||||
|
func get_brushes_search_path_in_order() -> Array:
|
||||||
|
var base_paths := get_search_paths_in_order()
|
||||||
|
return append_file_to_all(base_paths, brushes_data_subdirectory)
|
||||||
|
|
||||||
|
|
||||||
|
# Get the path that we are ok to be writing palettes to:
|
||||||
|
func get_palette_write_path() -> String:
|
||||||
|
return xdg_data_home.plus_file(palettes_data_subdirectory)
|
||||||
|
|
||||||
|
# Get the path that we are ok to be writing brushes to:
|
||||||
|
func get_brushes_write_path() -> String:
|
||||||
|
return xdg_data_home.plus_file(brushes_data_subdirectory)
|
||||||
|
|
||||||
|
# Ensure the user xdg directories exist:
|
||||||
|
func ensure_xdg_user_dirs_exist() -> void:
|
||||||
|
var base_dir := Directory.new()
|
||||||
|
base_dir.open(raw_xdg_data_home)
|
||||||
|
# Ensure the main config directory exists.
|
||||||
|
if not base_dir.dir_exists(xdg_data_home):
|
||||||
|
base_dir.make_dir(xdg_data_home)
|
||||||
|
|
||||||
|
var actual_data_dir := Directory.new()
|
||||||
|
actual_data_dir.open(xdg_data_home)
|
||||||
|
var palette_writing_dir := get_palette_write_path()
|
||||||
|
var brushes_writing_dir := get_brushes_write_path()
|
||||||
|
# Create the palette and brush dirs
|
||||||
|
if not actual_data_dir.dir_exists(palette_writing_dir):
|
||||||
|
print("Making directory %s" % [palette_writing_dir])
|
||||||
|
actual_data_dir.make_dir(palette_writing_dir)
|
||||||
|
if not actual_data_dir.dir_exists(brushes_writing_dir):
|
||||||
|
print("Making directory %s" % [brushes_writing_dir])
|
||||||
|
actual_data_dir.make_dir(brushes_writing_dir)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
|
#func _process(delta):
|
||||||
|
# pass
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 567 B After Width: | Height: | Size: 567 B |
Before Width: | Height: | Size: 573 B After Width: | Height: | Size: 573 B |
Before Width: | Height: | Size: 567 B After Width: | Height: | Size: 567 B |
Before Width: | Height: | Size: 567 B After Width: | Height: | Size: 567 B |
Before Width: | Height: | Size: 566 B After Width: | Height: | Size: 566 B |
Before Width: | Height: | Size: 177 B After Width: | Height: | Size: 177 B |
Before Width: | Height: | Size: 119 B After Width: | Height: | Size: 119 B |
Before Width: | Height: | Size: 511 B After Width: | Height: | Size: 511 B |
Before Width: | Height: | Size: 507 B After Width: | Height: | Size: 507 B |
Before Width: | Height: | Size: 512 B After Width: | Height: | Size: 512 B |
Before Width: | Height: | Size: 510 B After Width: | Height: | Size: 510 B |
Before Width: | Height: | Size: 516 B After Width: | Height: | Size: 516 B |
Before Width: | Height: | Size: 515 B After Width: | Height: | Size: 515 B |
Before Width: | Height: | Size: 99 B After Width: | Height: | Size: 99 B |
Before Width: | Height: | Size: 67 B After Width: | Height: | Size: 67 B |
Before Width: | Height: | Size: 67 B After Width: | Height: | Size: 67 B |