From f77b2d7126c0c8ef49856b1147985783b18fb019 Mon Sep 17 00:00:00 2001 From: QuentinCaffeino Date: Wed, 28 Mar 2018 21:56:29 +0200 Subject: [PATCH] Project refactor --- README.md | 8 +- .../fonts/RobotoMono}/LICENSE.txt | 0 .../fonts/RobotoMono}/RobotoMono-Bold.ttf | Bin .../RobotoMono}/RobotoMono-BoldItalic.ttf | Bin .../fonts/RobotoMono}/RobotoMono-Italic.ttf | Bin .../fonts/RobotoMono}/RobotoMono-Regular.ttf | Bin docs/Console.md | 1 + example/icon.png | Bin 4756 -> 0 bytes example/icon256.png | Bin 9159 -> 0 bytes example/project.godot | 33 -- example/scene.tscn | 124 ------- example/script.gd | 63 ---- example/vendor/quentincaffeino/console | 1 - example/screenshot.png => screenshot.png | Bin src/Argument/Argument.gd | 80 ++++ src/BaseCommands.gd | 118 +++--- src/Callback.gd | 121 +++--- src/Command/Command.gd | 162 ++++++++ src/Command/CommandAutocomplete.gd | 48 +++ src/Commands.gd | 73 ++++ src/Commands/Argument.gd | 32 -- src/Commands/ArgumentBuilder.gd | 38 -- src/Commands/Command.gd | 68 ---- src/Commands/CommandAutocomplete.gd | 48 --- src/Commands/CommandBuilder.gd | 87 ----- src/Commands/Commands.gd | 61 --- src/Commands/IArgument.gd | 27 -- src/Commands/ICommand.gd | 32 -- src/Commands/ICommands.gd | 39 -- src/Commands/Types/Bool.gd | 16 - src/Commands/Types/Float.gd | 14 - src/Commands/Types/FloatRange.gd | 33 -- src/Commands/Types/Int.gd | 14 - src/Commands/Types/IntRange.gd | 42 --- src/Commands/Types/TypesBuilder.gd | 17 - src/Commands/Types/Vector2.gd | 42 --- src/Console.gd | 347 +++++++++++------- src/Console.tscn | 8 +- src/History.gd | 34 +- src/IConsole.gd | 102 ----- src/Log.gd | 60 +-- src/RegExLib.gd | 32 +- src/{Commands => }/Types/Any.gd | 8 +- src/{Commands => }/Types/BaseRange.gd | 10 +- src/{Commands => }/Types/BaseType.gd | 20 +- src/Types/Bool.gd | 16 + src/{Commands => }/Types/Filter.gd | 22 +- src/Types/Float.gd | 14 + src/Types/FloatRange.gd | 33 ++ src/Types/Int.gd | 14 + src/Types/IntRange.gd | 42 +++ src/{Commands => }/Types/String.gd | 10 +- src/Types/TypesBuilder.gd | 17 + src/Types/Vector2.gd | 42 +++ 54 files changed, 974 insertions(+), 1299 deletions(-) rename {src/Fonts => assets/fonts/RobotoMono}/LICENSE.txt (100%) rename {src/Fonts => assets/fonts/RobotoMono}/RobotoMono-Bold.ttf (100%) rename {src/Fonts => assets/fonts/RobotoMono}/RobotoMono-BoldItalic.ttf (100%) rename {src/Fonts => assets/fonts/RobotoMono}/RobotoMono-Italic.ttf (100%) rename {src/Fonts => assets/fonts/RobotoMono}/RobotoMono-Regular.ttf (100%) delete mode 100644 example/icon.png delete mode 100644 example/icon256.png delete mode 100644 example/project.godot delete mode 100644 example/scene.tscn delete mode 100644 example/script.gd delete mode 120000 example/vendor/quentincaffeino/console rename example/screenshot.png => screenshot.png (100%) create mode 100644 src/Argument/Argument.gd create mode 100644 src/Command/Command.gd create mode 100644 src/Command/CommandAutocomplete.gd create mode 100644 src/Commands.gd delete mode 100644 src/Commands/Argument.gd delete mode 100644 src/Commands/ArgumentBuilder.gd delete mode 100644 src/Commands/Command.gd delete mode 100644 src/Commands/CommandAutocomplete.gd delete mode 100644 src/Commands/CommandBuilder.gd delete mode 100644 src/Commands/Commands.gd delete mode 100644 src/Commands/IArgument.gd delete mode 100644 src/Commands/ICommand.gd delete mode 100644 src/Commands/ICommands.gd delete mode 100644 src/Commands/Types/Bool.gd delete mode 100644 src/Commands/Types/Float.gd delete mode 100644 src/Commands/Types/FloatRange.gd delete mode 100644 src/Commands/Types/Int.gd delete mode 100644 src/Commands/Types/IntRange.gd delete mode 100644 src/Commands/Types/TypesBuilder.gd delete mode 100644 src/Commands/Types/Vector2.gd delete mode 100644 src/IConsole.gd rename src/{Commands => }/Types/Any.gd (70%) rename src/{Commands => }/Types/BaseRange.gd (57%) rename src/{Commands => }/Types/BaseType.gd (57%) create mode 100644 src/Types/Bool.gd rename src/{Commands => }/Types/Filter.gd (56%) create mode 100644 src/Types/Float.gd create mode 100644 src/Types/FloatRange.gd create mode 100644 src/Types/Int.gd create mode 100644 src/Types/IntRange.gd rename src/{Commands => }/Types/String.gd (61%) create mode 100644 src/Types/TypesBuilder.gd create mode 100644 src/Types/Vector2.gd diff --git a/README.md b/README.md index 0f16a1d..4a4cefd 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Godot Console In-game console for Godot, easily extensible with new commands. -![Quake-style console for Godot](https://github.com/QuentinCaffeino/godot-console/blob/master/example/screenshot.png) +![Quake-style console for Godot](https://github.com/QuentinCaffeino/godot-console/blob/master/screenshot.png) ## Features @@ -20,8 +20,8 @@ In-game console for Godot, easily extensible with new commands. ## Installation -1. Clone or download this repository. -2. Add `src/Console.tscn` to Autoload. +1. Clone or download this repository to your project folder. +2. Add `src/Console.tscn` to godot autoload as `Console`. 3. Add new actions to Input Map: `console_toggle`, `ui_up`, `ui_down` ## Example @@ -58,7 +58,7 @@ func print_hello(): More information about [**ARG_TYPE**](https://github.com/QuentinCaffeino/godot-console/blob/master/docs/Types.md) you can find in [this readme](https://github.com/QuentinCaffeino/godot-console/blob/master/docs/Types.md). -You can find more examples in [`example/script.gd`](https://github.com/QuentinCaffeino/godot-console/blob/master/example/script.gd) +You can find more examples in [`src/BaseCommands.gd`](https://github.com/QuentinCaffeino/godot-console/blob/master/src/BaseCommands.gd) ---------- diff --git a/src/Fonts/LICENSE.txt b/assets/fonts/RobotoMono/LICENSE.txt similarity index 100% rename from src/Fonts/LICENSE.txt rename to assets/fonts/RobotoMono/LICENSE.txt diff --git a/src/Fonts/RobotoMono-Bold.ttf b/assets/fonts/RobotoMono/RobotoMono-Bold.ttf similarity index 100% rename from src/Fonts/RobotoMono-Bold.ttf rename to assets/fonts/RobotoMono/RobotoMono-Bold.ttf diff --git a/src/Fonts/RobotoMono-BoldItalic.ttf b/assets/fonts/RobotoMono/RobotoMono-BoldItalic.ttf similarity index 100% rename from src/Fonts/RobotoMono-BoldItalic.ttf rename to assets/fonts/RobotoMono/RobotoMono-BoldItalic.ttf diff --git a/src/Fonts/RobotoMono-Italic.ttf b/assets/fonts/RobotoMono/RobotoMono-Italic.ttf similarity index 100% rename from src/Fonts/RobotoMono-Italic.ttf rename to assets/fonts/RobotoMono/RobotoMono-Italic.ttf diff --git a/src/Fonts/RobotoMono-Regular.ttf b/assets/fonts/RobotoMono/RobotoMono-Regular.ttf similarity index 100% rename from src/Fonts/RobotoMono-Regular.ttf rename to assets/fonts/RobotoMono/RobotoMono-Regular.ttf diff --git a/docs/Console.md b/docs/Console.md index 40fb605..777effe 100644 --- a/docs/Console.md +++ b/docs/Console.md @@ -24,4 +24,5 @@ | *int* unregister(*string* alias) | Unregister command | | void write(string message) | | | void writeLine(string message) | Append new-line character at the end of the message | +| void clear() | Clear console | | void toggleConsole() | Show console | diff --git a/example/icon.png b/example/icon.png deleted file mode 100644 index 5bf41d4a72e868a333dab23a5686fdc372ca05c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4756 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\" in the console. -Press ` to open console" -align = 1 -valign = 1 -percent_visible = 1.0 -lines_skipped = 0 -max_lines_visible = -1 - -[node name="ProgressBar" type="ProgressBar" parent="." index="1"] - -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 -margin_left = 131.0 -margin_top = 459.0 -margin_right = 856.0 -margin_bottom = 485.0 -rect_pivot_offset = Vector2( 0, 0 ) -mouse_filter = 0 -mouse_default_cursor_shape = 0 -size_flags_horizontal = 1 -size_flags_vertical = 0 -min_value = 0.0 -max_value = 100.0 -step = 1.0 -page = 0.0 -value = 0.0 -exp_edit = false -rounded = false -percent_visible = true - -[node name="AnimationPlayer" type="AnimationPlayer" parent="." index="2"] - -root_node = NodePath("..") -autoplay = "" -playback_process_mode = 1 -playback_default_blend_time = 0.0 -playback_speed = 1.0 -anims/test = SubResource( 2 ) -blend_times = [ ] - -[node name="CheckBox" type="CheckBox" parent="." index="3"] - -anchor_left = 0.0 -anchor_top = 0.0 -anchor_right = 0.0 -anchor_bottom = 0.0 -margin_left = 858.0 -margin_top = 417.0 -margin_right = 956.0 -margin_bottom = 440.0 -rect_pivot_offset = Vector2( 0, 0 ) -focus_mode = 2 -mouse_filter = 0 -mouse_default_cursor_shape = 0 -size_flags_horizontal = 1 -size_flags_vertical = 1 -toggle_mode = true -enabled_focus_mode = 2 -shortcut = null -group = null -text = "Checked???" -flat = false -align = 0 - -[node name="icon" type="Sprite" parent="." index="4"] - -position = Vector2( 502, 178 ) -scale = Vector2( 0.5, 0.5 ) -texture = ExtResource( 3 ) -_sections_unfolded = [ "Transform" ] - - diff --git a/example/script.gd b/example/script.gd deleted file mode 100644 index 6398439..0000000 --- a/example/script.gd +++ /dev/null @@ -1,63 +0,0 @@ - -extends Node - - -func _ready(): - Console.register('set_label_text', { - 'description': 'The text of example label', - 'args': [['text', TYPE_STRING]], - 'target': [$ExampleLabel, 'text'] - }) - - Console.register('change_label_text', { - 'description': 'Set the text of example label if condition is true', - 'args': [['condition', TYPE_BOOL], TYPE_STRING], - 'target': self - }) - - Console.register('pb_value', { - 'description': 'The level of progress bar', - 'args': [['value', Console.IntRange.new(0, 75, 6)]], - 'target': [$ProgressBar, 'value'] - }) - - Console.register('cb_checked', { - 'description': 'The value of check box', - 'args': [TYPE_BOOL], - 'target': [$CheckBox, 'pressed'] - }) - - Console.register('play_anim', { - 'description': 'Start playing animation on test scene with specific speed', - 'args': [['speed', TYPE_REAL]], - 'target': self - }) - - Console.register('filter_method', { - 'description': 'Filter input', - 'args': [['filter', Console.Filter.new(['hello', 'world'])]], - 'target': self - }) - - -func change_label_text(cond, text): - if cond: - $ExampleLabel.text = text - - -func play_anim(speed): - $AnimationPlayer.play('test') - $AnimationPlayer.set_speed_scale(speed) - - -func filter_method(filtered): - print(filtered) - - -func _exit_tree(): - Console.unregister('set_label_text') - Console.unregister('change_label_text') - Console.unregister('pb_value') - Console.unregister('cb_checked') - Console.unregister('play_anim') - Console.unregister('filter_method') diff --git a/example/vendor/quentincaffeino/console b/example/vendor/quentincaffeino/console deleted file mode 120000 index a1d005e..0000000 --- a/example/vendor/quentincaffeino/console +++ /dev/null @@ -1 +0,0 @@ -../../../src/ \ No newline at end of file diff --git a/example/screenshot.png b/screenshot.png similarity index 100% rename from example/screenshot.png rename to screenshot.png diff --git a/src/Argument/Argument.gd b/src/Argument/Argument.gd new file mode 100644 index 0000000..9e8be6c --- /dev/null +++ b/src/Argument/Argument.gd @@ -0,0 +1,80 @@ + +extends Reference + +const TypesBuilder = preload('../Types/TypesBuilder.gd') +const BaseType = preload('../Types/BaseType.gd') + + +enum ARGASSIG \ +{ + CANCELED = 2 +} + + +# @var string +var _name + +# @var BaseType +var _type + +# @var Variant +var value = null setget setValue, getValue + + +# @param string|null name +# @param BaseType type +func _init(name, type): + _name = name + _type = type + + +# @param Variant inValue +func setValue(inValue): # int + return _type.check(inValue) + + +func getValue(): # Variant + return _type.get() + + +func toString(): # string + var result = '' + + if _name: + result += _name + ':' + + result += _type.getName() + + return result + + +# @param string|null name +# @param int|BaseType type +static func build(name, type = 0): # Argument|int + # Define arument type + if !(typeof(type) == TYPE_OBJECT and type is BaseType): + type = TypesBuilder.build(type if typeof(type) == TYPE_INT else 0) + + if typeof(type) == TYPE_INT: + return FAILED + + return new(name, type) + + +# @param Array args +static func buildAll(args): # Array|int + var builtArgs = [] + + var tArg + for arg in args: + match typeof(arg): + TYPE_ARRAY: tArg = build(arg[0], arg[1] if arg.size() > 1 else 0) + TYPE_STRING: tArg = build(arg) + TYPE_OBJECT, TYPE_INT: tArg = build(null, arg) + + if typeof(tArg) == TYPE_INT: + return FAILED + + builtArgs.append(tArg) + + return builtArgs diff --git a/src/BaseCommands.gd b/src/BaseCommands.gd index 61d3adb..f188ca4 100644 --- a/src/BaseCommands.gd +++ b/src/BaseCommands.gd @@ -1,79 +1,75 @@ -extends Object +extends Reference func _init(): - Console.register('echo', { - 'description': 'Prints a string in console', - 'args': [TYPE_STRING], - 'target': [Console, 'writeLine'] - }) - - Console.register('history', { - 'description': 'Print all previous commands used during the session', - 'target': [Console._History, 'printAll'] - }) - - Console.register('commands', { - 'description': 'Lists all available commands', - 'target': [Console._Commands, 'printAll'] - }) - - Console.register('help', { - 'description': 'Outputs usage instructions', - 'args': [TYPE_STRING], - 'target': self - }) - - Console.register('quit', { - 'description': 'Exit application', - 'target': self - }) - - Console.register('clear', { - 'description': 'Clear the terminal', - 'target': self - }) - - Console.register('version', { - 'description': 'Shows engine vesion', - 'target': self - }) - - Console.register('fps_max', { - 'args': [Console.IntRange.new(10, 1000)], - 'description': 'The maximal framerate at which the application can run', - 'target': [Engine, 'set_target_fps'], - }) + Console.register('echo', { + 'description': 'Prints a string in console', + 'args': [TYPE_STRING], + 'target': [Console, 'writeLine'] + }) + + Console.register('history', { + 'description': 'Print all previous commands used during the session', + 'target': [Console._History, 'printAll'] + }) + + Console.register('commands', { + 'description': 'Lists all available commands', + 'target': [Console._Commands, 'printAll'] + }) + + Console.register('help', { + 'description': 'Outputs usage instructions', + 'args': [TYPE_STRING], + 'target': self + }) + + Console.register('quit', { + 'description': 'Exit application', + 'target': self + }) + + Console.register('clear', { + 'description': 'Clear the terminal', + 'target': Console + }) + + Console.register('version', { + 'description': 'Shows engine vesion', + 'target': self + }) + + Console.register('fps_max', { + 'args': [Console.IntRange.new(10, 1000)], + 'description': 'The maximal framerate at which the application can run', + 'target': [Engine, 'set_target_fps'], + }) # @param string|null command static func help(command = null): - if command: - var Command = Console._Commands.get(command) + if command: + var Command = Console._Commands.get(command) - if !Command: - Console.Log.warn('No such command') - return + if !Command: + Console.Log.warn('No such command') + return - Command.describe() - else: - Console.writeLine(\ - "Type [color=#ffff66][url=help]help[/url] [/color] show information about command.\n" + \ - "Type [color=#ffff66][url=commands]commands[/url][/color] to get a list of all commands.\n" + \ - "Type [color=#ffff66][url=quit]quit[/url][/color] to exit the application.") + Command.describe() + else: + Console.writeLine(\ + "Type [color=#ffff66][url=help]help[/url] [/color] show information about command.\n" + \ + "Type [color=#ffff66][url=commands]commands[/url][/color] to get a list of all commands.\n" + \ + "Type [color=#ffff66][url=quit]quit[/url][/color] to exit the application.") static func version(): # void - Console.writeLine(Engine.get_version_info()) + Console.writeLine(Engine.get_version_info()) # This function is called from scripts/console_commands.gd to avoid the # "Cannot access self without instance." error static func quit(): # void - Console.Log.warn('Quitting application...') - Console.get_tree().quit() - - -static func clear(): # void - Console._consoleText.set_bbcode('') + Console.Log.warn('Quitting application...') + Console.get_tree().quit() diff --git a/src/Callback.gd b/src/Callback.gd index 247a1bf..5065bb3 100644 --- a/src/Callback.gd +++ b/src/Callback.gd @@ -4,9 +4,9 @@ extends Reference enum TYPE \ { - UNKNOWN, - VARIABLE, - METHOD + UNKNOWN, + VARIABLE, + METHOD } # @var Reference @@ -23,58 +23,58 @@ var _type # @param string name # @param int type func _init(target, name, type = UNKNOWN): - _target = target - _name = name + _target = target + _name = name - if type == UNKNOWN: - type = getType(_target, _name) + if type == UNKNOWN: + type = getType(_target, _name) - _type = type + _type = type func getTarget(): # Reference - return _target + return _target func getName(): # string - return _name + return _name # Ensure callback target still exists func ensure(): # bool - if _target: - var wr = weakref(_target) - if wr.get_ref() == null: - print('Callback: ensure: Failed to call a callback, target was previously destroyed. (%s)' % _name) - return false - else: - print('Callback: ensure: Failed to call a callback, target was previously destroyed. (%s)' % _name) - return false + if _target: + var wr = weakref(_target) + if wr.get_ref() == null: + print('QC/Console/Callback: ensure: Failed to call a callback, target was previously destroyed. (%s)' % _name) + return false + else: + print('QC/Console/Callback: ensure: Failed to call a callback, target was previously destroyed. (%s)' % _name) + return false - if getType(_target, _name) == UNKNOWN: - print('Callback: ensure: Target is missing method/variable. (%s, %s)' % [_target, _name]) - return false + if getType(_target, _name) == UNKNOWN: + print('QC/Console/Callback: ensure: Target is missing method/variable. (%s, %s)' % [_target, _name]) + return false - return true + return true # @param Array argv func call(argv = []): # Variant - argv = array(argv) + argv = toArray(argv) - # Ensure callback target still exists - if !ensure(): - return + # Ensure callback target still exists + if !ensure(): + return - # Execute call - if _type == VARIABLE: - _target.set(_name, argv[0]) - return _target.get(_name) + # Execute call + if _type == VARIABLE: + _target.set(_name, argv[0]) + return _target.get(_name) - elif _type == METHOD: - return _target.callv(_name, argv) - - print('Callback: call: Unable to call unknown type.') + elif _type == METHOD: + return _target.callv(_name, argv) + + print('QC/Console/Callback: call: Unable to call unknown type.') # Use this method before creating a callback @@ -83,40 +83,45 @@ func call(argv = []): # Variant # @param string name # @param int type static func canCreate(target, name, type = UNKNOWN): # int - if typeof(target) != TYPE_OBJECT: - print('Callback: can_create: First argument must be target object. Provided: ' + str(typeof(target))) - return UNKNOWN + if typeof(target) != TYPE_OBJECT: + print('QC/Console/Callback: can_create: First argument must be target object. Provided: ' + str(typeof(target))) + return UNKNOWN - if typeof(name) != TYPE_STRING: - print('Callback: can_create: Second argument must be variable or method name. Provided: ' + str(typeof(name))) - return UNKNOWN + if typeof(name) != TYPE_STRING: + print('QC/Console/Callback: can_create: Second argument must be variable or method name. Provided: ' + str(typeof(name))) + return UNKNOWN - if type <= UNKNOWN or type > TYPE.size(): - type = getType(target, name) + if type <= UNKNOWN or type > TYPE.size(): + type = getType(target, name) - if type == UNKNOWN: - print('Callback: can_create: Target object doesn\'t have supplied method or variable.') + if type == UNKNOWN: + print('QC/Console/Callback: can_create: Target object doesn\'t have supplied method or variable.') - return type + return type # @param Reference target # @param string name static func getType(target, name): # int - # Is it a METHOD - if target.has_method(name): - return METHOD + # Is it a METHOD + if target.has_method(name): + return METHOD - # Is it a VARIABLE - if name in target: - return VARIABLE + # Is it a VARIABLE + if name in target: + return VARIABLE - return UNKNOWN + return UNKNOWN -# If passed arr as any value except Array, wrap it into array -static func array(arr): - if !(typeof(arr) >= TYPE_ARRAY and typeof(arr) <= TYPE_COLOR_ARRAY): - arr = [arr] - - return arr +# If passed `value` isn't type of array, wrap it into array. +# +# @param Variant value +static func toArray(value): # Array + if !(typeof(value) >= TYPE_ARRAY and typeof(value) <= TYPE_COLOR_ARRAY): + if typeof(value) != TYPE_NIL: + return [value] + else: + return [] + + return value diff --git a/src/Command/Command.gd b/src/Command/Command.gd new file mode 100644 index 0000000..c648887 --- /dev/null +++ b/src/Command/Command.gd @@ -0,0 +1,162 @@ + +extends Reference + +const Argument = preload('../Argument/Argument.gd') + + +# @var string +var _alias + +# @var Callback +var _target + +# @var Array +var _arguments = [] + +# @var string|null +var _description + + +# @param string alias +# @param Callback target +# @param Array arguments +# @param string|null description +func _init(alias, target, arguments, description = null): + _alias = str(alias) + _target = target + _arguments = arguments + + # Set description + _description = description + if !description: + Console.Log.info('No description provided for [b]' + _alias + '[/b] command', \ + 'Command: _init') + + +# @param Array inArgs +func run(inArgs): # int + # Get arguments + var args = [] + var argAssig + for i in range(_arguments.size()): + argAssig = _arguments[i].setValue(inArgs[i]) + + if argAssig == FAILED: + Console.Log.warn('Argument ' + str(i) + ': expected ' + _arguments[i]._type._name) + return FAILED + elif argAssig == Argument.CANCELED: + return OK + + args.append(_arguments[i].value) + + # Execute command + _target.call(args) + + return OK + + +func describe(): # void + Console.write("[color=#ffff66][url=" + _alias + "]" + _alias + "[/url][/color]") + + if _arguments.size() > 0: + for arg in _arguments: + Console.write(" [color=#88ffff]" + arg.toString() + "[/color]") + + if _description: + Console.write(' - ' + _description) + + Console.writeLine() + + +func requireArgs(): # int + return _arguments.size() + + +func requireStrings(): # bool + for arg in _arguments: + if arg._type._name == 'Any' or arg._type._type == TYPE_STRING: + return true + + return false + + +# @param string alias +# @param Dictionary params +static func build(alias, params): # Command + # Warn + if params.has('type'): + Console.Log.warn(\ + 'Using deprecated argument [b]type[/b] in [b]' + alias + '[/b].', \ + 'CommandBuilder: build') + if params.has('name'): + Console.Log.warn(\ + 'Using deprecated argument [b]name[/b] in [b]' + alias + '[/b].', \ + 'CommandBuilder: build') + + # Check target + if !params.has('target') or !params.target: + Console.Log.error(\ + 'Failed to register [b]' + alias + '[/b] command. Missing [b]target[/b] parametr.', \ + 'CommandBuilder: build') + return + + # Create target if old style used + if typeof(params.target) != TYPE_OBJECT or \ + !(params.target is Console.Callback): + + var target = params.target + if typeof(params.target) == TYPE_ARRAY: + target = params.target[0] + + var name = alias + + if typeof(params.target) == TYPE_ARRAY and \ + params.target.size() > 1 and \ + typeof(params.target[1]) == TYPE_STRING: + name = params.target[1] + elif params.has('name'): + name = params.name + + if Console.Callback.canCreate(target, name): + params.target = Console.Callback.new(target, name) + else: + params.target = null + + if params.target: + if not params.target is Console.Callback: + Console.Log.error(\ + 'Failed to register [b]' + alias + \ + '[/b] command. Failed to create callback to target', \ + 'CommandBuilder: build') + return + else: + Console.Log.error(\ + 'Failed to register [b]' + alias + \ + '[/b] command. Failed to create callback to target', \ + 'CommandBuilder: build') + return + + # Set arguments + if params.target._type == Console.Callback.VARIABLE and params.has('args'): + # Ignore all arguments except first cause variable takes only one arg + params.args = [params.args[0]] + + if params.has('arg'): + params.args = Argument.buildAll([ params.arg ]) + params.erase('arg') + elif params.has('args'): + params.args = Argument.buildAll(params.args) + else: + params.args = [] + + if typeof(params.args) == TYPE_INT: + Console.Log.error(\ + 'Failed to register [b]' + alias + \ + '[/b] command. Wrong [b]arguments[/b] parametr.', \ + 'CommandBuilder: build') + return + + if !params.has('description'): + params.description = null + + return new(alias, params.target, params.args, params.description) diff --git a/src/Command/CommandAutocomplete.gd b/src/Command/CommandAutocomplete.gd new file mode 100644 index 0000000..8bfd07b --- /dev/null +++ b/src/Command/CommandAutocomplete.gd @@ -0,0 +1,48 @@ + +extends Reference + + +# @var string +var _filter = null + +# @var Array +var _filtered = [] + +# @param int +var _current = -1 + + +# @param string filter +func filter(filter): # void + if _filter == filter: + return + + var willBeFiltered = Console._Commands._commands + # Little optimization to filter from already filtered if... + if _filter and filter.length() > _filter.length() and filter.begins_with(_filter): + willBeFiltered = _filtered + + _filter = filter + + # Filter commands + for command in willBeFiltered: + if command.begins_with(filter): + _filtered.append(command) + + +func next(): # string + if _filtered.size() > 0: + if _current == _filtered.size() - 1: + _current = -1 + + _current += 1 + + return _filtered[_current] + else: + reset() + + +func reset(): # void + _filter = null + _filtered = [] + _current = -1 diff --git a/src/Commands.gd b/src/Commands.gd new file mode 100644 index 0000000..de90cc4 --- /dev/null +++ b/src/Commands.gd @@ -0,0 +1,73 @@ + +extends Reference + +const Command = preload('Command/Command.gd') + + +# @var CommandAutocomplete +var Autocomplete = preload('Command/CommandAutocomplete.gd').new() setget _setProtected + +# @var Dictionary +var _commands = {} + + +# @param string alias +# @param Dictionary params +func register(alias, params): # int + # Check if already exists + if has(alias): + Console.Log.warn('Failed to register [b]' + \ + alias + '[/b]. Command already exists.', 'Commands: register') + return FAILED + + # Register command + var command = Command.build(alias, params) + + if command: + _commands[alias] = command + return OK + + return FAILED + + +# @param string alias +func unregister(alias): # int + if !has(alias): + Console.Log.info('Attempt to unregister nonexistent command [b]' + \ + alias + '[/b].', 'Commands: unregister') + return FAILED + + _commands.erase(alias) + return OK + + +# @param string alias +func get(alias): # Command + if has(alias): + return _commands[alias] + + if Console.submitAutocomplete: + # Try autocomplete + var filteredCommands = [] + + for command in _commands: + if command.begins_with(alias): + filteredCommands.append(command) + + if filteredCommands.size() == 1: + return _commands[filteredCommands[0]] + + +# @param string alias +func has(alias): # bool + return _commands.has(alias) + + +func printAll(): # void + for command in _commands: + _commands[command].describe() + + +func _setProtected(value): # void + Console.Log.warn('Trying to set a protected variable, ignoring. Provided ' + str(value), \ + 'Commands') diff --git a/src/Commands/Argument.gd b/src/Commands/Argument.gd deleted file mode 100644 index a0d30de..0000000 --- a/src/Commands/Argument.gd +++ /dev/null @@ -1,32 +0,0 @@ - -extends 'IArgument.gd' - -const TypesBuilder = preload('Types/TypesBuilder.gd') -const BaseType = preload('Types/BaseType.gd') - - -# @param string|null name -# @param BaseType type -func _init(name, type): - _name = name - _type = type - - -# @param Variant inValue -func setValue(inValue): # int - return _type.check(inValue) - - -func getValue(): # Variant - return _type.get() - - -func toString(): # string - var result = '' - - if _name: - result += _name + ':' - - result += _type.getName() - - return result diff --git a/src/Commands/ArgumentBuilder.gd b/src/Commands/ArgumentBuilder.gd deleted file mode 100644 index b667e59..0000000 --- a/src/Commands/ArgumentBuilder.gd +++ /dev/null @@ -1,38 +0,0 @@ - -extends Object - -const Argument = preload('Argument.gd') -const TypesBuilder = preload('Types/TypesBuilder.gd') -const BaseType = preload('Types/BaseType.gd') - - -# @param string|null name -# @param int|BaseType type -static func build(name, type = 0): # Argument|int - # Define arument type - if !(typeof(type) == TYPE_OBJECT and type is BaseType): - type = TypesBuilder.build(type if typeof(type) == TYPE_INT else 0) - - if typeof(type) == TYPE_INT: - return FAILED - - return Argument.new(name, type) - - -# @param Array args -static func buildAll(args): # Array|int - var builtArgs = [] - - var tArg - for arg in args: - match typeof(arg): - TYPE_ARRAY: tArg = build(arg[0], arg[1] if arg.size() > 1 else 0) - TYPE_STRING: tArg = build(arg) - TYPE_OBJECT, TYPE_INT: tArg = build(null, arg) - - if typeof(tArg) == TYPE_INT: - return FAILED - - builtArgs.append(tArg) - - return builtArgs diff --git a/src/Commands/Command.gd b/src/Commands/Command.gd deleted file mode 100644 index 9cfd99e..0000000 --- a/src/Commands/Command.gd +++ /dev/null @@ -1,68 +0,0 @@ - -extends 'ICommand.gd' - -const ArgumentB = preload('ArgumentBuilder.gd') -const Argument = preload('Argument.gd') - - -# @param string alias -# @param Callback target -# @param Array arguments -# @param string|null description -func _init(alias, target, arguments, description = null): - _alias = str(alias) - _target = target - _arguments = arguments - - # Set description - _description = description - if !description: - Console.Log.info('No description provided for [b]' + _alias + '[/b] command', \ - 'Command: _init') - - -# @param Array inArgs -func run(inArgs): # int - # Get arguments - var args = [] - var argAssig - for i in range(_arguments.size()): - argAssig = _arguments[i].setValue(inArgs[i]) - - if argAssig == FAILED: - Console.Log.warn('Argument ' + str(i) + ': expected ' + _arguments[i]._type._name) - return FAILED - elif argAssig == Argument.CANCELED: - return OK - - args.append(_arguments[i].value) - - # Execute command - _target.call(args) - - return OK - - -func describe(): # void - Console.write("[color=#ffff66][url=" + _alias + "]" + _alias + "[/url][/color]") - - if _arguments.size() > 0: - for arg in _arguments: - Console.write(" [color=#88ffff]" + arg.toString() + "[/color]") - - if _description: - Console.write(' - ' + _description) - - Console.writeLine() - - -func requireArgs(): # int - return _arguments.size() - - -func requireStrings(): # bool - for arg in _arguments: - if arg._type._name == 'Any' or arg._type._type == TYPE_STRING: - return true - - return false diff --git a/src/Commands/CommandAutocomplete.gd b/src/Commands/CommandAutocomplete.gd deleted file mode 100644 index a5da3c7..0000000 --- a/src/Commands/CommandAutocomplete.gd +++ /dev/null @@ -1,48 +0,0 @@ - -extends Object - - -# @var string -var _filter = null - -# @var Array -var _filtered = [] - -# @param int -var _current = -1 - - -# @param string filter -func filter(filter): # void - if _filter == filter: - return - - var willBeFiltered = Console._Commands._commands - # Little optimization to filter from already filtered if... - if _filter and filter.length() > _filter.length() and filter.begins_with(_filter): - willBeFiltered = _filtered - - _filter = filter - - # Filter commands - for command in willBeFiltered: - if command.begins_with(filter): - _filtered.append(command) - - -func next(): # string - if _filtered.size() > 0: - if _current == _filtered.size() - 1: - _current = -1 - - _current += 1 - - return _filtered[_current] - else: - reset() - - -func reset(): # void - _filter = null - _filtered = [] - _current = -1 diff --git a/src/Commands/CommandBuilder.gd b/src/Commands/CommandBuilder.gd deleted file mode 100644 index 28fb79e..0000000 --- a/src/Commands/CommandBuilder.gd +++ /dev/null @@ -1,87 +0,0 @@ - -extends Object - -const Command = preload('Command.gd') -const ArgumentB = preload('ArgumentBuilder.gd') - - -# @param string alias -# @param Dictionary params -static func build(alias, params): # Command - # Warn - if params.has('type'): - Console.Log.warn(\ - 'Using deprecated argument [b]type[/b] in [b]' + alias + '[/b].', \ - 'CommandBuilder: build') - if params.has('name'): - Console.Log.warn(\ - 'Using deprecated argument [b]name[/b] in [b]' + alias + '[/b].', \ - 'CommandBuilder: build') - - # Check target - if !params.has('target') or !params.target: - Console.Log.error(\ - 'Failed to register [b]' + alias + '[/b] command. Missing [b]target[/b] parametr.', \ - 'CommandBuilder: build') - return - - # Create target if old style used - if typeof(params.target) != TYPE_OBJECT or \ - !(params.target is Console.Callback): - - var target = params.target - if typeof(params.target) == TYPE_ARRAY: - target = params.target[0] - - var name = alias - - if typeof(params.target) == TYPE_ARRAY and \ - params.target.size() > 1 and \ - typeof(params.target[1]) == TYPE_STRING: - name = params.target[1] - elif params.has('name'): - name = params.name - - if Console.Callback.canCreate(target, name): - params.target = Console.Callback.new(target, name) - else: - params.target = null - - if params.target: - if not params.target is Console.Callback: - Console.Log.error(\ - 'Failed to register [b]' + alias + \ - '[/b] command. Failed to create callback to target', \ - 'CommandBuilder: build') - return - else: - Console.Log.error(\ - 'Failed to register [b]' + alias + \ - '[/b] command. Failed to create callback to target', \ - 'CommandBuilder: build') - return - - # Set arguments - if params.target._type == Console.Callback.VARIABLE and params.has('args'): - # Ignore all arguments except first cause variable takes only one arg - params.args = [params.args[0]] - - if params.has('arg'): - params.args = ArgumentB.buildAll([ params.arg ]) - params.erase('arg') - elif params.has('args'): - params.args = ArgumentB.buildAll(params.args) - else: - params.args = [] - - if typeof(params.args) == TYPE_INT: - Console.Log.error(\ - 'Failed to register [b]' + alias + \ - '[/b] command. Wrong [b]arguments[/b] parametr.', \ - 'CommandBuilder: build') - return - - if !params.has('description'): - params.description = null - - return Command.new(alias, params.target, params.args, params.description) diff --git a/src/Commands/Commands.gd b/src/Commands/Commands.gd deleted file mode 100644 index 15881c2..0000000 --- a/src/Commands/Commands.gd +++ /dev/null @@ -1,61 +0,0 @@ - -extends 'ICommands.gd' - -const CommandB = preload('CommandBuilder.gd') - - -# @param string alias -# @param Dictionary params -func register(alias, params): # int - # Check if already exists - if has(alias): - Console.Log.warn('Failed to register [b]' + \ - alias + '[/b]. Command already exists.', 'Commands: register') - return FAILED - - # Register command - var command = CommandB.build(alias, params) - - if command: - _commands[alias] = command - return OK - - return FAILED - - -# @param string alias -func unregister(alias): # int - if !has(alias): - Console.Log.info('Tried to unregister nonexistent command [b]' + \ - alias + '[/b].', 'Commands: unregister') - return FAILED - - _commands.erase(alias) - return OK - - -# @param string alias -func get(alias): # Command - if has(alias): - return _commands[alias] - - if Console.submitAutocomplete: - # Try autocomplete - var filteredCommands = [] - - for command in _commands: - if command.begins_with(alias): - filteredCommands.append(command) - - if filteredCommands.size() == 1: - return _commands[filteredCommands[0]] - - -# @param string alias -func has(alias): # bool - return _commands.has(alias) - - -func printAll(): # void - for command in _commands: - _commands[command].describe() diff --git a/src/Commands/IArgument.gd b/src/Commands/IArgument.gd deleted file mode 100644 index 8c64f7e..0000000 --- a/src/Commands/IArgument.gd +++ /dev/null @@ -1,27 +0,0 @@ - -extends Object - - -enum ARGASSIG \ -{ - CANCELED = 2 -} - - -# @var string -var _name - -# @var BaseType -var _type - -# @var Variant -var value = null setget setValue, getValue - - -# @param Variant inValue -func setValue(inValue): # int - pass - - -func getValue(): # Variant - pass diff --git a/src/Commands/ICommand.gd b/src/Commands/ICommand.gd deleted file mode 100644 index 4d39e3b..0000000 --- a/src/Commands/ICommand.gd +++ /dev/null @@ -1,32 +0,0 @@ - -extends Object - - -# @var string -var _alias - -# @var Callback -var _target - -# @var Array -var _arguments = [] - -# @var string|null -var _description - - -# @param Array inArgs -func run(inArgs): # int - pass - - -func describe(): # void - pass - - -func requireArgs(): # int - pass - - -func requireStrings(): # bool - pass diff --git a/src/Commands/ICommands.gd b/src/Commands/ICommands.gd deleted file mode 100644 index b5f9101..0000000 --- a/src/Commands/ICommands.gd +++ /dev/null @@ -1,39 +0,0 @@ - -extends Object - - -# @var CommandAutocomplete -var Autocomplete = preload('CommandAutocomplete.gd').new() setget _setProtected - -# @var Dictionary -var _commands = {} - - -# @param string alias -# @param Dictionary params -func register(alias, params): # int - pass - - -# @param string alias -func deregister(alias): # void - pass - - -# @param string alias -func get(alias): # Command - pass - - -# @param string alias -func has(alias): # bool - pass - - -func printAll(): # void - pass - - -func _setProtected(value): # void - Console.Log.warn('Trying to set a protected variable, ignoring. Provided ' + str(value), \ - 'ICommands') diff --git a/src/Commands/Types/Bool.gd b/src/Commands/Types/Bool.gd deleted file mode 100644 index 02ef94b..0000000 --- a/src/Commands/Types/Bool.gd +++ /dev/null @@ -1,16 +0,0 @@ - -extends 'BaseType.gd' - - -func _init(): - _name = 'Bool' - _type = TYPE_BOOL - - -func get(): # bool - if _rematch and _rematch is RegExMatch: - var tmp = _rematch.get_string() - - return true if tmp == '1' or tmp == 'true' else false - - return false diff --git a/src/Commands/Types/Float.gd b/src/Commands/Types/Float.gd deleted file mode 100644 index a5488df..0000000 --- a/src/Commands/Types/Float.gd +++ /dev/null @@ -1,14 +0,0 @@ - -extends 'BaseType.gd' - - -func _init(): - _name = 'Float' - _type = TYPE_REAL - - -func get(): # float - if _rematch and _rematch is RegExMatch: - return float(_rematch.get_string().replace(',', '.')) - - return 0.0 diff --git a/src/Commands/Types/FloatRange.gd b/src/Commands/Types/FloatRange.gd deleted file mode 100644 index 5fe5eaf..0000000 --- a/src/Commands/Types/FloatRange.gd +++ /dev/null @@ -1,33 +0,0 @@ - -extends 'BaseRange.gd' - - -# @param float inMinValue -# @param float inMaxValue -# @param float inStep -func _init(inMinValue = 0, inMaxValue = 100, inStep = 0): - _name = 'FloatRange' - minValue = float(inMinValue) - maxValue = float(inMaxValue) - step = float(inStep) - - -# @param Varian value -func check(value): # int - value = clamp(float(value), minValue, maxValue) - - # Find closest step - if step != 0 and value != minValue: - var prevVal = minValue - var curVal = minValue - - while curVal < value: - prevVal = curVal - curVal += step - - if curVal - value < value - prevVal and curVal <= maxValue: - _value = curVal - else: - _value = prevVal - - return OK diff --git a/src/Commands/Types/Int.gd b/src/Commands/Types/Int.gd deleted file mode 100644 index 0acde0f..0000000 --- a/src/Commands/Types/Int.gd +++ /dev/null @@ -1,14 +0,0 @@ - -extends 'BaseType.gd' - - -func _init(): - _name = 'Int' - _type = TYPE_INT - - -func get(): # int - if _rematch and _rematch is RegExMatch: - return int(_rematch.get_string()) - - return 0 diff --git a/src/Commands/Types/IntRange.gd b/src/Commands/Types/IntRange.gd deleted file mode 100644 index b8d85a6..0000000 --- a/src/Commands/Types/IntRange.gd +++ /dev/null @@ -1,42 +0,0 @@ - -extends 'BaseRange.gd' - - -# @var bool -var rounded = true setget _setRounded - - -# @param int inMinValue -# @param int inMaxValue -# @param int inStep -func _init(inMinValue = 0, inMaxValue = 100, inStep = 1): - _name = 'IntRange' - minValue = int(inMinValue) - maxValue = int(inMaxValue) - step = int(inStep) - - -# @param Varian value -func check(value): # int - value = clamp(int(value), minValue, maxValue) - - # Find closest step - if step != 1 and value != minValue: - var prevVal = minValue - var curVal = minValue - - while curVal < value: - prevVal = curVal - curVal += step - - if curVal - value < value - prevVal and curVal <= maxValue: - _value = curVal - else: - _value = prevVal - - return OK - - -# @param bool value -func _setRounded(value): - rounded = (value == true) diff --git a/src/Commands/Types/TypesBuilder.gd b/src/Commands/Types/TypesBuilder.gd deleted file mode 100644 index 0ea7d45..0000000 --- a/src/Commands/Types/TypesBuilder.gd +++ /dev/null @@ -1,17 +0,0 @@ - -extends Object - - -const TypesList = [ - preload('Any.gd'), - preload('Bool.gd'), - preload('Int.gd'), - preload('Float.gd'), - preload('String.gd'), - preload('Vector2.gd'), -] - - -# @param int type -static func build(type): # BaseType - return TypesList[type if type >= 0 and type < TypesList.size() else 0].new() diff --git a/src/Commands/Types/Vector2.gd b/src/Commands/Types/Vector2.gd deleted file mode 100644 index 245595a..0000000 --- a/src/Commands/Types/Vector2.gd +++ /dev/null @@ -1,42 +0,0 @@ - -extends 'BaseType.gd' - - -# @var Vector2|null -var _value - - -func _init(): - _name = 'Vector2' - _type = TYPE_VECTOR2 - - -# @param Variant value -func check(value): # int - var values = str(value).split(',', false) - var values_size = values.size() - if values_size < 2: - if values_size == 1: - values.append(0) - else: - return FAILED - - var regex = Console.RegExLib.get(TYPE_REAL) - # Check each number - if regex and regex is RegEx: - for v in [0, 1]: - _rematch = regex.search(values[v]) - - if !_rematch or !(_rematch is RegExMatch): - return FAILED - - # Save value - _value = Vector2(values[0], values[1]) - - return OK - - - -func get(): # Vector2|null - return _value - diff --git a/src/Console.gd b/src/Console.gd index 949620e..9ed009e 100644 --- a/src/Console.gd +++ b/src/Console.gd @@ -1,5 +1,61 @@ -extends 'IConsole.gd' +extends CanvasLayer + +const BaseCommands = preload('BaseCommands.gd') +const Callback = preload('Callback.gd') + +### Custom console types +const IntRange = preload('Types/IntRange.gd') +const FloatRange = preload('Types/FloatRange.gd') +const Filter = preload('Types/Filter.gd') + + +enum CMDTYPE \ +{ + VARIABLE, + METHOD +} + + +# @var Commands +var _Commands = preload('Commands.gd').new() + +# @var History +var _History = preload('History.gd').new() + +# @var Log +var Log = preload('Log.gd').new() setget _setProtected + +# @var RegExLib +var RegExLib = preload('RegExLib.gd').new() setget _setProtected + +# Used to clear text from bb tags +# @var RegEx +var _eraseTrash + +# @var bool +var isConsoleShown = true setget _setProtected + +# @var string|null +var _currCmdHandler = null + +# @var string|null +var _currCmd = null + +# @var bool +var debugMode = false + +# @var bool +var submitAutocomplete = true + +# @var string +export(String) var action_console_toggle = 'console_toggle' + +# @var string +export(String) var action_history_up = 'ui_up' + +# @var string +export(String) var action_history_down = 'ui_down' ### Console nodes @@ -10,199 +66,208 @@ onready var _animationPlayer = $ConsoleBox/AnimationPlayer func _init(): - # Used to clear text from bb tags - _eraseTrash = RegExLib.get('console.eraseTrash') + # Used to clear text from bb tags + _eraseTrash = RegExLib.get('console.eraseTrash') func _ready(): - # Allow selecting console text - _consoleText.set_selection_enabled(true) - # Follow console output (for scrolling) - _consoleText.set_scroll_follow(true) - # React to clicks on console urls - _consoleText.connect('meta_clicked', self, '_handleUrlClick') + # Allow selecting console text + _consoleText.set_selection_enabled(true) + # Follow console output (for scrolling) + _consoleText.set_scroll_follow(true) + # React to clicks on console urls + _consoleText.connect('meta_clicked', self, '_handleUrlClick') - # Hide console by default - _consoleBox.hide() - _animationPlayer.connect("animation_finished", self, "_toggleAnimationFinished") - toggleConsole() + # Hide console by default + _consoleBox.hide() + _animationPlayer.connect("animation_finished", self, "_toggleAnimationFinished") + toggleConsole() - # Console keyboard control - set_process_input(true) + # Console keyboard control + set_process_input(true) - _consoleLine.connect('text_entered', self, '_handleEnteredCommand') + _consoleLine.connect('text_entered', self, '_handleEnteredCommand') - # By default we show help - var v = Engine.get_version_info() - writeLine(\ - ProjectSettings.get_setting("application/config/name") + \ - " (Godot " + str(v.major) + '.' + str(v.minor) + '.' + str(v.patch) + ' ' + v.status+")\n" + \ - "Type [color=#ffff66][url=help]help[/url][/color] to get more information about usage") + # Show some info + var v = Engine.get_version_info() + writeLine(\ + ProjectSettings.get_setting("application/config/name") + \ + " (Godot " + str(v.major) + '.' + str(v.minor) + '.' + str(v.patch) + ' ' + v.status+")\n" + \ + "Type [color=#ffff66][url=help]help[/url][/color] to get more information about usage") - # Init base commands - BaseCommands.new() + # Init base commands + BaseCommands.new() # @param Event e func _input(e): - if Input.is_action_just_pressed(action_console_toggle): - toggleConsole() + if Input.is_action_just_pressed(action_console_toggle): + toggleConsole() - # Show prev line in history - if Input.is_action_just_pressed(action_history_up): - _currCmd = _History.prev() + # Show prev line in history + if Input.is_action_just_pressed(action_history_up): + _currCmd = _History.prev() - if _currCmdHandler == null: - _currCmdHandler = _consoleLine.text + if _currCmdHandler == null: + _currCmdHandler = _consoleLine.text - # Show next line in history - if Input.is_action_just_pressed(action_history_down): - _currCmd = _History.next() + # Show next line in history + if Input.is_action_just_pressed(action_history_down): + _currCmd = _History.next() - if !_currCmd and _currCmdHandler != null: - _currCmd = _currCmdHandler - _currCmdHandler = null + if !_currCmd and _currCmdHandler != null: + _currCmd = _currCmdHandler + _currCmdHandler = null - # Autocomplete on TAB - if _consoleLine.text and _consoleLine.has_focus() and Input.is_key_pressed(KEY_TAB): - if !_Commands.Autocomplete._filtered.has(_consoleLine.text): - _currCmdHandler = _consoleLine.text - _Commands.Autocomplete.reset() + # Autocomplete on TAB + if _consoleLine.text and _consoleLine.has_focus() and Input.is_key_pressed(KEY_TAB): + if !_Commands.Autocomplete._filtered.has(_consoleLine.text): + _currCmdHandler = _consoleLine.text + _Commands.Autocomplete.reset() - _Commands.Autocomplete.filter(_currCmdHandler) - _currCmd = _Commands.Autocomplete.next() + _Commands.Autocomplete.filter(_currCmdHandler) + _currCmd = _Commands.Autocomplete.next() - # Finish - if _currCmd != null: - _setConsoleLine(_currCmd) - _currCmd = null - _consoleLine.accept_event() + # Finish + if _currCmd != null: + _setConsoleLine(_currCmd) + _currCmd = null + _consoleLine.accept_event() # @param string command func _handleEnteredCommand(command): # void - if command.empty(): - return - - # Some preparations - _History.reset() - _Commands.Autocomplete.reset() - command = _eraseTrash.sub(command, '', true) - - # Get command name - var cmdName = command.split(' ', false) - if typeof(cmdName) != TYPE_STRING_ARRAY: - Log.warn('Could not get command name', \ - 'Console: _handleEnteredCommand') - return - cmdName = cmdName[0] - - var Command = _Commands.get(cmdName) - - if !Command: - Log.warn('No such command', \ - 'Console: _handleEnteredCommand') - return - - # Get args - var args = [] - var cmdArgs = null - if Command.requireArgs(): - cmdArgs = command.substr(cmdName.length() + 1, command.length()) - - if Command._target._type == Console.Callback.VARIABLE or Command._arguments.size() == 1: - args.append(cmdArgs) - elif Command.requireStrings(): - - var isString = null - var prevDelimiter = 0 - - var i = 0 - while Command.requireArgs() != args.size(): - if cmdArgs[i] == '"' or cmdArgs[i] == "'": - if !isString: - isString = cmdArgs[i] - elif cmdArgs[i] == isString and cmdArgs[i - 1 if i > 0 else 0] != '\\': - isString = null - - if !isString: - if prevDelimiter and (cmdArgs[i] == '"' or cmdArgs[i] == "'"): - args.append(cmdArgs.substr(prevDelimiter + 1, i - 3).replace('\\' + \ - str(cmdArgs[prevDelimiter]), cmdArgs[prevDelimiter])) - prevDelimiter = i + 1 - elif cmdArgs[i] == ' ' and cmdArgs[i + 1 if i < cmdArgs.length() - 1 else i] != ' ': - args.append(cmdArgs.substr(prevDelimiter, i)) - prevDelimiter = i + 1 - - i += 1 - - else: - args = cmdArgs.split(' ', false) - - # Execute - var finCommand = Command._alias - if cmdArgs: - finCommand += ' ' + cmdArgs - - _History.push(finCommand) - writeLine('[color=#999999]$[/color] ' + finCommand) - Command.run(args) - _consoleLine.clear() + if command.empty(): + return + + # Some preparations + _History.reset() + _Commands.Autocomplete.reset() + command = _eraseTrash.sub(command, '', true) + + # Get command name + var cmdName = command.split(' ', false) + if typeof(cmdName) != TYPE_STRING_ARRAY: + Log.warn('Could not get command name', \ + 'Console: _handleEnteredCommand') + return + cmdName = cmdName[0] + + var Command = _Commands.get(cmdName) + + if !Command: + Log.warn('No such command', \ + 'Console: _handleEnteredCommand') + return + + # Get args + var args = [] + var cmdArgs = null + if Command.requireArgs(): + cmdArgs = command.substr(cmdName.length() + 1, command.length()) + + if Command._target._type == Console.Callback.VARIABLE or Command._arguments.size() == 1: + args.append(cmdArgs) + elif Command.requireStrings(): + + var isString = null + var prevDelimiter = 0 + + var i = 0 + while Command.requireArgs() != args.size(): + if cmdArgs[i] == '"' or cmdArgs[i] == "'": + if !isString: + isString = cmdArgs[i] + elif cmdArgs[i] == isString and cmdArgs[i - 1 if i > 0 else 0] != '\\': + isString = null + + if !isString: + if prevDelimiter and (cmdArgs[i] == '"' or cmdArgs[i] == "'"): + args.append(cmdArgs.substr(prevDelimiter + 1, i - 3).replace('\\' + \ + str(cmdArgs[prevDelimiter]), cmdArgs[prevDelimiter])) + prevDelimiter = i + 1 + elif cmdArgs[i] == ' ' and cmdArgs[i + 1 if i < cmdArgs.length() - 1 else i] != ' ': + args.append(cmdArgs.substr(prevDelimiter, i)) + prevDelimiter = i + 1 + + i += 1 + + else: + args = cmdArgs.split(' ', false) + + # Execute + var finCommand = Command._alias + if cmdArgs: + finCommand += ' ' + cmdArgs + + _History.push(finCommand) + writeLine('[color=#999999]$[/color] ' + finCommand) + Command.run(args) + _consoleLine.clear() # @param string url func _handleUrlClick(url): # void - _setConsoleLine(url + ' ') + _setConsoleLine(url + ' ') # @param string text # @param bool moveCaretToEnd func _setConsoleLine(text, moveCaretToEnd = true): # void - _consoleLine.text = text - _consoleLine.grab_focus() + _consoleLine.text = text + _consoleLine.grab_focus() - if moveCaretToEnd: - _consoleLine.caret_position = text.length() + if moveCaretToEnd: + _consoleLine.caret_position = text.length() # @param string alias # @param Dictionary params func register(alias, params): # int - return _Commands.register(alias, params) + return _Commands.register(alias, params) # @param string alias func unregister(alias): # int - return _Commands.unregister(alias) + return _Commands.unregister(alias) # @param string message func write(message): # void - message = str(message) - print(_eraseTrash.sub(message, '', true)) - _consoleText.set_bbcode(_consoleText.get_bbcode() + message) - + message = str(message) + _consoleText.set_bbcode(_consoleText.get_bbcode() + message) + print(_eraseTrash.sub(message, '', true)) + # @param string message func writeLine(message = ''): # void - message = str(message) - print(_eraseTrash.sub(message, '', true)) - _consoleText.set_bbcode(_consoleText.get_bbcode() + message + '\n') + message = str(message) + _consoleText.set_bbcode(_consoleText.get_bbcode() + message + '\n') + print(_eraseTrash.sub(message, '', true)) + + +func clear(): # void + _consoleText.set_bbcode('') func toggleConsole(): # void - # Open the console - if !isConsoleShown: - _consoleBox.show() - _consoleLine.clear() - _consoleLine.grab_focus() - _animationPlayer.play_backwards('fade') - else: - _animationPlayer.play('fade') + # Open the console + if !isConsoleShown: + _consoleBox.show() + _consoleLine.clear() + _consoleLine.grab_focus() + _animationPlayer.play_backwards('fade') + else: + _animationPlayer.play('fade') - isConsoleShown = !isConsoleShown + isConsoleShown = !isConsoleShown func _toggleAnimationFinished(animation): # void - if !isConsoleShown: - _consoleBox.hide() + if !isConsoleShown: + _consoleBox.hide() + + +func _setProtected(value): # void + Log.warn('Trying to set a protected variable, ignoring. Provided ' + str(value), \ + 'Console: _setProtected') diff --git a/src/Console.tscn b/src/Console.tscn index 8aafb3d..b572f1d 100644 --- a/src/Console.tscn +++ b/src/Console.tscn @@ -1,10 +1,10 @@ [gd_scene load_steps=15 format=2] [ext_resource path="Console.gd" type="Script" id=1] -[ext_resource path="Fonts/RobotoMono-BoldItalic.ttf" type="DynamicFontData" id=2] -[ext_resource path="Fonts/RobotoMono-Italic.ttf" type="DynamicFontData" id=3] -[ext_resource path="Fonts/RobotoMono-Bold.ttf" type="DynamicFontData" id=4] -[ext_resource path="Fonts/RobotoMono-Regular.ttf" type="DynamicFontData" id=5] +[ext_resource path="../assets/fonts/RobotoMono/RobotoMono-BoldItalic.ttf" type="DynamicFontData" id=2] +[ext_resource path="../assets/fonts/RobotoMono/RobotoMono-Italic.ttf" type="DynamicFontData" id=3] +[ext_resource path="../assets/fonts/RobotoMono/RobotoMono-Bold.ttf" type="DynamicFontData" id=4] +[ext_resource path="../assets/fonts/RobotoMono/RobotoMono-Regular.ttf" type="DynamicFontData" id=5] [sub_resource type="Animation" id=1] diff --git a/src/History.gd b/src/History.gd index e53b8eb..9f6f609 100644 --- a/src/History.gd +++ b/src/History.gd @@ -1,5 +1,5 @@ -extends Object +extends Reference # @param Array @@ -11,32 +11,32 @@ var _current = -1 # @param string command func push(command): # void - if _history.size() > 0 and _history[_history.size() - 1] == command: - return + if _history.size() > 0 and _history[_history.size() - 1] == command: + return - _history.append(command) + _history.append(command) func prev(): # string - if _history.size() > 0 and _current < _history.size() - 1: - _current += 1 - return _history[_history.size() - _current - 1] + if _history.size() > 0 and _current < _history.size() - 1: + _current += 1 + return _history[_history.size() - _current - 1] func next(): # string - if _history.size() > 0 and _current > 0: - _current -= 1 - return _history[_history.size() - _current - 1] - else: - reset() + if _history.size() > 0 and _current > 0: + _current -= 1 + return _history[_history.size() - _current - 1] + else: + reset() func reset(): # void - _current = -1 + _current = -1 func printAll(): # void - for i in range(_history.size()): - Console.writeLine(\ - '[b]' + str(i + 1) + '.[/b] [color=#ffff66][url=' + \ - _history[i] + ']' + _history[i] + '[/url][/color]') + for i in range(_history.size()): + Console.writeLine(\ + '[b]' + str(i + 1) + '.[/b] [color=#ffff66][url=' + \ + _history[i] + ']' + _history[i] + '[/url][/color]') diff --git a/src/IConsole.gd b/src/IConsole.gd deleted file mode 100644 index b2ab096..0000000 --- a/src/IConsole.gd +++ /dev/null @@ -1,102 +0,0 @@ - -extends CanvasLayer - -const BaseCommands = preload('BaseCommands.gd') -const Callback = preload('Callback.gd') - -### Custom console types -const IntRange = preload('Commands/Types/IntRange.gd') -const FloatRange = preload('Commands/Types/FloatRange.gd') -const Filter = preload('Commands/Types/Filter.gd') - - -enum CMDTYPE \ -{ - VARIABLE, - METHOD -} - - -# @var Commands -var _Commands = preload('Commands/Commands.gd').new() setget _setProtected - -# @var History -var _History = preload('History.gd').new() setget _setProtected - -# @var Log -var Log = preload('Log.gd').new() setget _setProtected - -# @var RegExLib -var RegExLib = preload('RegExLib.gd').new() setget _setProtected - -# Used to clear text from bb tags -# @var RegEx -var _eraseTrash - -# @var bool -var isConsoleShown = true setget _setProtected - -# @var string|null -var _currCmdHandler = null - -# @var string|null -var _currCmd = null - -# @var bool -var debugMode = false - -# @var bool -var submitAutocomplete = true - -# @var string -export(String) var action_console_toggle = 'console_toggle' - -# @var string -export(String) var action_history_up = 'ui_up' - -# @var string -export(String) var action_history_down = 'ui_down' - - -# @param string command -func _handleEnteredCommand(command): # void - pass - - -# @param string url -func _handleUrlClick(url): # void - pass - - -# @param string alias -# @param Dictionary params -func register(alias, params): # int - pass - - -# @param string alias -func unregister(alias): # int - pass - - -# @param string message -func write(message): # void - pass - - -# @param string message -func writeLine(message = ''): # void - pass - - -func toggleConsole(): # void - pass - - -func _toggleAnimationFinished(animation): # void - pass - - -func _setProtected(value): # void - Log.warn('Trying to set a protected variable, ignoring. Provided ' + str(value), \ - 'IConsole: _setProtected') diff --git a/src/Log.gd b/src/Log.gd index e3c9fe1..09cf147 100644 --- a/src/Log.gd +++ b/src/Log.gd @@ -1,13 +1,13 @@ -extends Object +extends Reference enum TYPE \ { - INFO, - WARNING, - ERROR, - NONE + INFO, + WARNING, + ERROR, + NONE } @@ -17,61 +17,61 @@ var logLevel = WARNING setget setLogLevel # @param int inlogLevel func setLogLevel(inlogLevel = INFO): # void - logLevel = inlogLevel + logLevel = inlogLevel # @param string message # @param int type func log(message, type = INFO): # void - match type: - INFO: info(message) - WARNING: warn(message) - ERROR: error(message) + match type: + INFO: info(message) + WARNING: warn(message) + ERROR: error(message) # @param string message # @param string debugInfo func info(message, debugInfo = ''): # void - if logLevel <= INFO: - var write = '[color=blue][INFO][/color] ' + if logLevel <= INFO: + var write = '[color=blue][INFO][/color] ' - if Console.debugMode and debugInfo: - write += str(debugInfo) + ': ' + if Console.debugMode and debugInfo: + write += str(debugInfo) + ': ' - Console.writeLine(write + str(message)) + Console.writeLine(write + str(message)) # @param string message # @param string debugInfo func warn(message, debugInfo = ''): # void - if logLevel <= WARNING: - var write = '[color=yellow][WARNING][/color] ' + if logLevel <= WARNING: + var write = '[color=yellow][WARNING][/color] ' - if Console.debugMode and debugInfo: - write += str(debugInfo) + ': ' + if Console.debugMode and debugInfo: + write += str(debugInfo) + ': ' - Console.writeLine(write + str(message)) + Console.writeLine(write + str(message)) # @param string message # @param string debugInfo func error(message, debugInfo = ''): # void - if logLevel <= ERROR: - var write = '[color=red][ERROR][/color] ' + if logLevel <= ERROR: + var write = '[color=red][ERROR][/color] ' - if Console.debugMode and debugInfo: - write += str(debugInfo) + ': ' + if Console.debugMode and debugInfo: + write += str(debugInfo) + ': ' - Console.writeLine(write + str(message)) + Console.writeLine(write + str(message)) # @param string message # @param string debugInfo func debug(message, debugInfo = ''): # void - if Console.debugMode: - var write = '[color=green][DEBUG][/color] ' + if Console.debugMode: + var write = '[color=green][DEBUG][/color] ' - if debugInfo: - write += str(debugInfo) + ': ' + if debugInfo: + write += str(debugInfo) + ': ' - Console.writeLine(write + str(message)) + Console.writeLine(write + str(message)) diff --git a/src/RegExLib.gd b/src/RegExLib.gd index 860ae97..3f1e974 100644 --- a/src/RegExLib.gd +++ b/src/RegExLib.gd @@ -1,13 +1,13 @@ -extends Object +extends Reference const _patterns = { - '1': '^(1|0|true|false)$', # bool - '2': '^[+-]?\\d+$', # int - '3': '^[+-]?([0-9]*[\\.]?[0-9]+|[0-9]+[\\.]?[0-9]*)([eE][+-]?[0-9]+)?$', # float + '1': '^(1|0|true|false)$', # bool + '2': '^[+-]?\\d+$', # int + '3': '^[+-]?([0-9]*[\\.]?[0-9]+|[0-9]+[\\.]?[0-9]*)([eE][+-]?[0-9]+)?$', # float - 'console.eraseTrash': '\\[[\\/]?[a-z\\=\\#0-9\\ \\_\\-\\,\\.]+\\]', + 'console.eraseTrash': '\\[[\\/]?[a-z\\=\\#0-9\\ \\_\\-\\,\\.]+\\]', } # @var Array @@ -16,18 +16,18 @@ var _compiled = {} # @param int type func get(type): # RegEx|int - var strType = str(type) + var strType = str(type) - if !_compiled.has(strType): - if !_patterns.has(strType): - return FAILED + if !_compiled.has(strType): + if !_patterns.has(strType): + return FAILED - var r = RegEx.new() - r.compile(_patterns[strType]) + var r = RegEx.new() + r.compile(_patterns[strType]) - if r and r is RegEx: - _compiled[strType] = r - else: - return FAILED + if r and r is RegEx: + _compiled[strType] = r + else: + return FAILED - return _compiled[strType] + return _compiled[strType] diff --git a/src/Commands/Types/Any.gd b/src/Types/Any.gd similarity index 70% rename from src/Commands/Types/Any.gd rename to src/Types/Any.gd index 1487831..5821394 100644 --- a/src/Commands/Types/Any.gd +++ b/src/Types/Any.gd @@ -7,14 +7,14 @@ var _value func _init(): - _name = 'Any' + _name = 'Any' # @param Varian value func check(value): # int - _value = value - return OK + _value = value + return OK func get(): # Variant - return _value + return _value diff --git a/src/Commands/Types/BaseRange.gd b/src/Types/BaseRange.gd similarity index 57% rename from src/Commands/Types/BaseRange.gd rename to src/Types/BaseRange.gd index d270e33..c81ff2a 100644 --- a/src/Commands/Types/BaseRange.gd +++ b/src/Types/BaseRange.gd @@ -16,13 +16,13 @@ var step func get(): # int|float - return _value + return _value func getName(): # string - var name = _name + '(' + str(minValue) + '-' + str(maxValue) + var name = _name + '(' + str(minValue) + '-' + str(maxValue) - if step != 1: - name += ', step: ' + str(step) + if step != 1: + name += ', step: ' + str(step) - return name + ')' + return name + ')' diff --git a/src/Commands/Types/BaseType.gd b/src/Types/BaseType.gd similarity index 57% rename from src/Commands/Types/BaseType.gd rename to src/Types/BaseType.gd index 1885d83..3b4eb5a 100644 --- a/src/Commands/Types/BaseType.gd +++ b/src/Types/BaseType.gd @@ -1,10 +1,10 @@ -extends Object +extends Reference enum CHECK \ { - CANCELED = 2 + CANCELED = 2 } @@ -24,21 +24,21 @@ var _rematch # # @param Varian value func check(value): # int - var regex = Console.RegExLib.get(_type) + var regex = Console.RegExLib.get(_type) - if regex and regex is RegEx: - _rematch = regex.search(value) + if regex and regex is RegEx: + _rematch = regex.search(value) - if _rematch and _rematch is RegExMatch: - return OK + if _rematch and _rematch is RegExMatch: + return OK - return FAILED + return FAILED # Returns assigned variable func get(): # Variant - pass + pass func getName(): # string - return _name + return _name diff --git a/src/Types/Bool.gd b/src/Types/Bool.gd new file mode 100644 index 0000000..39de6a4 --- /dev/null +++ b/src/Types/Bool.gd @@ -0,0 +1,16 @@ + +extends 'BaseType.gd' + + +func _init(): + _name = 'Bool' + _type = TYPE_BOOL + + +func get(): # bool + if _rematch and _rematch is RegExMatch: + var tmp = _rematch.get_string() + + return true if tmp == '1' or tmp == 'true' else false + + return false diff --git a/src/Commands/Types/Filter.gd b/src/Types/Filter.gd similarity index 56% rename from src/Commands/Types/Filter.gd rename to src/Types/Filter.gd index e305ccd..8491aa5 100644 --- a/src/Commands/Types/Filter.gd +++ b/src/Types/Filter.gd @@ -3,8 +3,8 @@ extends 'BaseType.gd' enum MODE { - ALLOW, - DENY + ALLOW, + DENY } @@ -21,20 +21,20 @@ var _value # @param Array fliterList # @param int mode func _init(fliterList, mode = ALLOW): - _name = 'Filter' - _fliterList = fliterList - _mode = mode + _name = 'Filter' + _fliterList = fliterList + _mode = mode # @param Variant value func check(value): # int - if (_mode == ALLOW and _fliterList.has(value)) or \ - (_mode == DENY and !_fliterList.has(value)): - _value = value - return OK + if (_mode == ALLOW and _fliterList.has(value)) or \ + (_mode == DENY and !_fliterList.has(value)): + _value = value + return OK - return CANCELED + return CANCELED func get(): # Variant - return _value + return _value diff --git a/src/Types/Float.gd b/src/Types/Float.gd new file mode 100644 index 0000000..87db8d5 --- /dev/null +++ b/src/Types/Float.gd @@ -0,0 +1,14 @@ + +extends 'BaseType.gd' + + +func _init(): + _name = 'Float' + _type = TYPE_REAL + + +func get(): # float + if _rematch and _rematch is RegExMatch: + return float(_rematch.get_string().replace(',', '.')) + + return 0.0 diff --git a/src/Types/FloatRange.gd b/src/Types/FloatRange.gd new file mode 100644 index 0000000..de0ca5b --- /dev/null +++ b/src/Types/FloatRange.gd @@ -0,0 +1,33 @@ + +extends 'BaseRange.gd' + + +# @param float inMinValue +# @param float inMaxValue +# @param float inStep +func _init(inMinValue = 0, inMaxValue = 100, inStep = 0): + _name = 'FloatRange' + minValue = float(inMinValue) + maxValue = float(inMaxValue) + step = float(inStep) + + +# @param Varian value +func check(value): # int + value = clamp(float(value), minValue, maxValue) + + # Find closest step + if step != 0 and value != minValue: + var prevVal = minValue + var curVal = minValue + + while curVal < value: + prevVal = curVal + curVal += step + + if curVal - value < value - prevVal and curVal <= maxValue: + _value = curVal + else: + _value = prevVal + + return OK diff --git a/src/Types/Int.gd b/src/Types/Int.gd new file mode 100644 index 0000000..2186bb5 --- /dev/null +++ b/src/Types/Int.gd @@ -0,0 +1,14 @@ + +extends 'BaseType.gd' + + +func _init(): + _name = 'Int' + _type = TYPE_INT + + +func get(): # int + if _rematch and _rematch is RegExMatch: + return int(_rematch.get_string()) + + return 0 diff --git a/src/Types/IntRange.gd b/src/Types/IntRange.gd new file mode 100644 index 0000000..e628dce --- /dev/null +++ b/src/Types/IntRange.gd @@ -0,0 +1,42 @@ + +extends 'BaseRange.gd' + + +# @var bool +var rounded = true setget _setRounded + + +# @param int inMinValue +# @param int inMaxValue +# @param int inStep +func _init(inMinValue = 0, inMaxValue = 100, inStep = 1): + _name = 'IntRange' + minValue = int(inMinValue) + maxValue = int(inMaxValue) + step = int(inStep) + + +# @param Varian value +func check(value): # int + value = clamp(int(value), minValue, maxValue) + + # Find closest step + if step != 1 and value != minValue: + var prevVal = minValue + var curVal = minValue + + while curVal < value: + prevVal = curVal + curVal += step + + if curVal - value < value - prevVal and curVal <= maxValue: + _value = curVal + else: + _value = prevVal + + return OK + + +# @param bool value +func _setRounded(value): + rounded = (value == true) diff --git a/src/Commands/Types/String.gd b/src/Types/String.gd similarity index 61% rename from src/Commands/Types/String.gd rename to src/Types/String.gd index 673ff96..50052c7 100644 --- a/src/Commands/Types/String.gd +++ b/src/Types/String.gd @@ -7,15 +7,15 @@ var _value func _init(): - _name = 'String' - _type = TYPE_STRING + _name = 'String' + _type = TYPE_STRING # @param Varian value func check(value): # int - _value = str(value) - return OK + _value = str(value) + return OK func get(): # string - return _value + return _value diff --git a/src/Types/TypesBuilder.gd b/src/Types/TypesBuilder.gd new file mode 100644 index 0000000..e8a9593 --- /dev/null +++ b/src/Types/TypesBuilder.gd @@ -0,0 +1,17 @@ + +extends Reference + + +const TypesList = [ + preload('Any.gd'), + preload('Bool.gd'), + preload('Int.gd'), + preload('Float.gd'), + preload('String.gd'), + preload('Vector2.gd'), +] + + +# @param int type +static func build(type): # BaseType + return TypesList[type if type >= 0 and type < TypesList.size() else 0].new() diff --git a/src/Types/Vector2.gd b/src/Types/Vector2.gd new file mode 100644 index 0000000..f84ec95 --- /dev/null +++ b/src/Types/Vector2.gd @@ -0,0 +1,42 @@ + +extends 'BaseType.gd' + + +# @var Vector2|null +var _value + + +func _init(): + _name = 'Vector2' + _type = TYPE_VECTOR2 + + +# @param Variant value +func check(value): # int + var values = str(value).split(',', false) + var values_size = values.size() + if values_size < 2: + if values_size == 1: + values.append(0) + else: + return FAILED + + var regex = Console.RegExLib.get(TYPE_REAL) + # Check each number + if regex and regex is RegEx: + for v in [0, 1]: + _rematch = regex.search(values[v]) + + if !_rematch or !(_rematch is RegExMatch): + return FAILED + + # Save value + _value = Vector2(values[0], values[1]) + + return OK + + + +func get(): # Vector2|null + return _value +