extends Node # Get hold of the brushes, including random brushes (subdirectories and % files # in them, non % files get loaded independently.) nyaaa # Returns a list of [ # [non random single png files in the root subdir], # { # 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 func find_brushes(brushes_dir : Directory, path : String) -> Array: var subdirectories := [] var found_random_brush := 0 path = Global.root_directory.plus_file(path) brushes_dir.open(path) brushes_dir.list_dir_begin(true) var file := brushes_dir.get_next() while file != "": if file.get_extension().to_upper() == "PNG": var image := Image.new() var err := image.load(path.plus_file(file)) if err == OK: if "%" in file: if found_random_brush == 0: found_random_brush = Global.file_brush_container.get_child_count() image.convert(Image.FORMAT_RGBA8) Global.custom_brushes.append(image) Global.create_brush_button(image, Global.Brush_Types.RANDOM_FILE, file.trim_suffix(".png")) else: var brush_button = Global.file_brush_container.get_child(found_random_brush) brush_button.random_brushes.append(image) else: image.convert(Image.FORMAT_RGBA8) Global.custom_brushes.append(image) Global.create_brush_button(image, Global.Brush_Types.FILE, file.trim_suffix(".png")) elif file.get_extension() == "": # Probably a directory var subdir := "./%s" % [file] if brushes_dir.dir_exists(subdir): # If it's an actual directory subdirectories.append(subdir) file = brushes_dir.get_next() brushes_dir.list_dir_end() return subdirectories func import_gpl(path : String) -> Palette: var result : Palette = null var file = File.new() if file.file_exists(path): file.open(path, File.READ) var text = file.get_as_text() var lines = text.split('\n') var line_number := 0 var comments := "" for line in lines: # Check if valid Gimp Palette Library file if line_number == 0: if line != "GIMP Palette": break else: result = Palette.new() var name_start = path.find_last('/') + 1 var name_end = path.find_last('.') if name_end > name_start: result.name = path.substr(name_start, name_end - name_start) # Comments if line.begins_with('#'): comments += line.trim_prefix('#') + '\n' pass elif line_number > 0 && line.length() >= 12: line = line.replace("\t", " ") var color_data : PoolStringArray = line.split(" ", false, 4) var red : float = color_data[0].to_float() / 255.0 var green : float = color_data[1].to_float() / 255.0 var blue : float = color_data[2].to_float() / 255.0 var color = Color(red, green, blue) result.add_color(color, color_data[3]) line_number += 1 if result: result.comments = comments file.close() return result func import_png_palette(path: String) -> Palette: var result: Palette = null var image := Image.new() var err := image.load(path) if err != OK: # An error occured return null var height: int = image.get_height() var width: int = image.get_width() result = Palette.new() # Iterate all pixels and store unique colors to palete image.lock() for y in range(0, height): for x in range(0, width): var color: Color = image.get_pixel(x, y) if not result.has_color(color): result.add_color(color, "#" + color.to_html()) image.unlock() var name_start = path.find_last('/') + 1 var name_end = path.find_last('.') if name_end > name_start: result.name = path.substr(name_start, name_end - name_start) return result pass