Skip to content

Commit

Permalink
Implement a basic CLI
Browse files Browse the repository at this point in the history
Supports exporting images & spritesheets with frame, direction, scale and output file name specification. Also added some informative arguments that simply print out some data.
  • Loading branch information
OverloadedOrama committed Apr 1, 2024
1 parent 183bee6 commit af01234
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 5 deletions.
10 changes: 10 additions & 0 deletions src/Autoload/Export.gd
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,16 @@ func file_format_description(format_enum: int) -> String:
return ""


func get_file_format_from_extension(file_extension: String) -> FileFormat:
if not file_extension.begins_with("."):
file_extension = "." + file_extension
for format: FileFormat in file_format_dictionary:
var extension: String = file_format_dictionary[format][0]
if file_extension.to_lower() == extension:
return format
return FileFormat.PNG


## True when exporting to .gif, .apng and video
## False when exporting to .png, .jpg and static .webp
func is_single_file_format(project := Global.current_project) -> bool:
Expand Down
82 changes: 77 additions & 5 deletions src/Main.gd
Original file line number Diff line number Diff line change
Expand Up @@ -193,13 +193,85 @@ func _handle_cmdline_arguments() -> void:
var args := OS.get_cmdline_args()
if args.is_empty():
return

# Load the files first
for arg in args:
var file_path := arg
if file_path.is_relative_path():
file_path = OS.get_executable_path().get_base_dir().path_join(arg)
OpenSave.handle_loading_file(file_path)

var project := Global.current_project
# True when exporting from the CLI.
# Exporting should be done last, this variable helps with that
var should_export := false
for i in args.size(): # Handle the rest of the CLI arguments
var arg := args[i]
var arg_lower := arg.to_lower()

This comment has been minimized.

Copy link
@gruelingpine185

gruelingpine185 Apr 2, 2024

  • It is a user error if they don't use the right case for CLI arguments. In this case, you can exit with an error and possibly suggest similar commands valid arguments with something similar to Levenshtein Distance (if you want to be fancy like git).
frc utf8 $? ➜ git subnodule add
git: 'subnodule' is not a git command. See 'git --help'.

The most similar command is
	submodule
  • Doing this also significantly reduces your options for flags. There are 26 letters in the alphabet. With both lower- and uppercase letters, there are 52 single character options. Subtract 2 for the reserved -h and -v flags and you are left with 50. This is if you leave the arguments as is. You will only have 24 single character options (2 reserved already excluded) if you make all flags lowercase. The few flag suggestions I made here use up a quarter of the total options already.

This comment has been minimized.

Copy link
@OverloadedOrama

OverloadedOrama Apr 3, 2024

Author Member

Good point, your suggestions have been implemented in 1c8d81d and #1006.

if arg.begins_with("-") or arg.begins_with("--"):
# TODO: Add code to handle custom command line arguments
continue
else:
OpenSave.handle_loading_file(arg)
if arg_lower == "--pixelorama-version":
print(Global.current_version)
elif arg_lower == "--size":
print(project.size)
elif arg_lower == "--framecount":
print(project.frames.size())
elif arg_lower == "--export":
should_export = true
elif arg_lower == "--spritesheet":
Export.current_tab = Export.ExportTab.SPRITESHEET
should_export = true
elif arg_lower == "--output" or arg_lower == "-o":
if i + 1 < args.size():
var next_argument := args[i + 1]
project.file_name = next_argument.get_basename()
var extension := next_argument.get_extension()
project.file_format = Export.get_file_format_from_extension(extension)
elif arg_lower == "--scale":
if i + 1 < args.size():
var next_argument := args[i + 1]
if next_argument.is_valid_float():
Export.resize = next_argument.to_float() * 100
elif arg_lower == "--frames":
if i + 1 < args.size():
var next_argument := args[i + 1]
if next_argument.contains("-"):
var frame_numbers := next_argument.split("-")
if frame_numbers.size() > 1:
project.selected_cels.clear()
var frame_number_1 := 0
if frame_numbers[0].is_valid_int():
frame_number_1 = frame_numbers[0].to_int() - 1
frame_number_1 = clampi(frame_number_1, 0, project.frames.size() - 1)
var frame_number_2 := project.frames.size() - 1
if frame_numbers[1].is_valid_int():
frame_number_2 = frame_numbers[1].to_int() - 1
frame_number_2 = clampi(frame_number_2, 0, project.frames.size() - 1)
for frame in range(frame_number_1, frame_number_2 + 1):
project.selected_cels.append([frame, project.current_layer])
project.change_cel(frame)
Export.frame_current_tag = Export.ExportFrames.SELECTED_FRAMES
elif next_argument.is_valid_int():
var frame_number := next_argument.to_int() - 1
frame_number = clampi(frame_number, 0, project.frames.size() - 1)
project.selected_cels = [[frame_number, project.current_layer]]
project.change_cel(frame_number)
Export.frame_current_tag = Export.ExportFrames.SELECTED_FRAMES
elif arg_lower == "--direction":
if i + 1 < args.size():
var next_argument := args[i + 1].to_lower()
if next_argument == "0" or next_argument.contains("forward"):
Export.direction = Export.AnimationDirection.FORWARD
elif next_argument == "1" or next_argument.contains("backward"):
Export.direction = Export.AnimationDirection.BACKWARDS
elif next_argument == "2" or next_argument.contains("ping"):
Export.direction = Export.AnimationDirection.PING_PONG
else:
print(Export.AnimationDirection.keys()[Export.direction])
else:
print(Export.AnimationDirection.keys()[Export.direction])
elif arg_lower == "--split-layers":
Export.split_layers = true
if should_export:
Export.external_export(project)


func _notification(what: int) -> void:
Expand Down

0 comments on commit af01234

Please sign in to comment.