fix: implement varargs for ESC commands. 'custom' makes use of this #592
This commit is contained in:
@@ -1,16 +1,17 @@
|
||||
# `custom object node func_name [params]`
|
||||
# `custom object node func_name [params...]`
|
||||
#
|
||||
#
|
||||
# Executes the specified Godot function. This function must be in a script
|
||||
# attached to a child node of a registered `ESCitem`.
|
||||
# attached to a child node of a registered `ESCItem`.
|
||||
#
|
||||
# **Parameters**
|
||||
#
|
||||
# - *object*: Global ID of the target `ESCItem`
|
||||
# - *node*: Name of the child node of the target `ESCItem`
|
||||
# - *func_name*: Name of the function to be called
|
||||
# - params: Any arguments to be passed to the function (array and object parameters are not supported). Multiple
|
||||
# parameters can be passed by using comma-separated values inside a string
|
||||
# - params: Any arguments to be passed to the function (array and object parameters are not supported).
|
||||
# Multiple parameters can be passed by simply passing them in as additional arguments separated by
|
||||
# spaces, e.g. `custom the_object the_node the_function arg1 arg2 arg3`
|
||||
#
|
||||
# @ESC
|
||||
extends ESCBaseCommand
|
||||
@@ -22,7 +23,9 @@ func configure() -> ESCCommandArgumentDescriptor:
|
||||
return ESCCommandArgumentDescriptor.new(
|
||||
3,
|
||||
[TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_ARRAY],
|
||||
[null, null, null, []]
|
||||
[null, null, null, []],
|
||||
[true],
|
||||
true
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -42,14 +42,14 @@ func _init(command_string):
|
||||
).strip_edges()
|
||||
)
|
||||
for parameter in parsed_parameters.split(" "):
|
||||
if parameter.begins_with('"') and parameter.ends_with('"'):
|
||||
if len(parameter) > 1 and parameter.begins_with('"') and parameter.ends_with('"'):
|
||||
parameters.append(
|
||||
parameter
|
||||
)
|
||||
elif ":" in parameter and '"' in parameter:
|
||||
quote_open = true
|
||||
parameter_values.append(parameter)
|
||||
elif parameter.begins_with('"'):
|
||||
elif not quote_open and parameter.begins_with('"'):
|
||||
quote_open = true
|
||||
parameter_values.append(parameter)
|
||||
elif parameter.ends_with('"'):
|
||||
|
||||
@@ -30,24 +30,30 @@ var defaults: Array = []
|
||||
# Whether to strip quotes on specific arguments
|
||||
var strip_quotes: Array = []
|
||||
|
||||
# Whether the final argument is a series of varargs
|
||||
var has_varargs: bool = false
|
||||
|
||||
|
||||
# Initialize the descriptor
|
||||
func _init(
|
||||
p_min_args: int = 0,
|
||||
p_types: Array = [],
|
||||
p_defaults: Array = [],
|
||||
p_strip_quotes: Array = [true]
|
||||
p_strip_quotes: Array = [true],
|
||||
p_has_varargs: bool = false
|
||||
):
|
||||
max_args = p_types.size()
|
||||
min_args = p_min_args
|
||||
types = p_types
|
||||
defaults = p_defaults
|
||||
strip_quotes = p_strip_quotes
|
||||
has_varargs = p_has_varargs
|
||||
|
||||
|
||||
# Combine the default argument values with the given arguments
|
||||
func prepare_arguments(arguments: Array) -> Array:
|
||||
var complete_arguments = defaults
|
||||
var varargs = []
|
||||
|
||||
for index in range(arguments.size()):
|
||||
# If we have too many arguments passed in, complete_arguments won't
|
||||
@@ -55,22 +61,32 @@ func prepare_arguments(arguments: Array) -> Array:
|
||||
# to avoid duplicating validation code, just grow complete_arguments
|
||||
# since the arguments won't be used anyway.
|
||||
if index >= complete_arguments.size():
|
||||
complete_arguments.append(arguments[index])
|
||||
continue
|
||||
|
||||
complete_arguments[index] = escoria.utils.get_typed_value(
|
||||
arguments[index],
|
||||
types[index]
|
||||
)
|
||||
var strip = strip_quotes[0]
|
||||
if strip_quotes.size() == complete_arguments.size():
|
||||
strip = strip_quotes[index]
|
||||
|
||||
if strip and typeof(complete_arguments[index]) == TYPE_STRING:
|
||||
complete_arguments[index] = complete_arguments[index].replace(
|
||||
'"',
|
||||
''
|
||||
if has_varargs:
|
||||
varargs.append(arguments[index])
|
||||
else:
|
||||
complete_arguments.append(arguments[index])
|
||||
elif index == complete_arguments.size() - 1 and has_varargs:
|
||||
# Varargs are a special case and need to be gathered and added at
|
||||
# the end as an array, untyped and unchecked. They should also only
|
||||
# appear at the very end of a command's argument list.
|
||||
varargs.append(arguments[index])
|
||||
else:
|
||||
complete_arguments[index] = escoria.utils.get_typed_value(
|
||||
arguments[index],
|
||||
types[index]
|
||||
)
|
||||
var strip = strip_quotes[0]
|
||||
if strip_quotes.size() == complete_arguments.size():
|
||||
strip = strip_quotes[index]
|
||||
|
||||
if strip and typeof(complete_arguments[index]) == TYPE_STRING:
|
||||
complete_arguments[index] = complete_arguments[index].replace(
|
||||
'"',
|
||||
''
|
||||
)
|
||||
|
||||
if has_varargs:
|
||||
complete_arguments[complete_arguments.size() - 1] = varargs
|
||||
|
||||
return complete_arguments
|
||||
|
||||
@@ -91,7 +107,7 @@ func validate(command: String, arguments: Array) -> bool:
|
||||
]
|
||||
)
|
||||
|
||||
if arguments.size() > self.max_args:
|
||||
if arguments.size() > self.max_args and not has_varargs:
|
||||
escoria.logger.report_errors(
|
||||
"ESCCommandArgumentDescriptor:validate()",
|
||||
[
|
||||
@@ -104,6 +120,11 @@ func validate(command: String, arguments: Array) -> bool:
|
||||
if arguments[index] == null:
|
||||
# No type checking for null values
|
||||
continue
|
||||
|
||||
if has_varargs and index == arguments.size() - 1:
|
||||
# If we have varargs at the end, do not validate them.
|
||||
continue
|
||||
|
||||
var correct = false
|
||||
var types_index = index
|
||||
if types_index > types.size():
|
||||
|
||||
@@ -75,7 +75,8 @@ func set_scene(p_scene: Node) -> void:
|
||||
#
|
||||
# - p_scene: The scene currently being initialized by set_scene.
|
||||
func finish_current_scene_init(p_scene: Node) -> void:
|
||||
move_child(p_scene, 0)
|
||||
if is_a_parent_of(p_scene):
|
||||
move_child(p_scene, 0)
|
||||
|
||||
current_scene = p_scene
|
||||
|
||||
|
||||
Reference in New Issue
Block a user