-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathConsole.gd
274 lines (198 loc) · 6.76 KB
/
Console.gd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
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
onready var _consoleBox = $ConsoleBox
onready var _consoleText = $ConsoleBox/Container/ConsoleText
onready var _consoleLine = $ConsoleBox/Container/LineEdit
onready var _animationPlayer = $ConsoleBox/AnimationPlayer
func _init():
# 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')
# Hide console by default
_consoleBox.hide()
_animationPlayer.connect("animation_finished", self, "_toggleAnimationFinished")
toggleConsole()
# Console keyboard control
set_process_input(true)
_consoleLine.connect('text_entered', self, '_handleEnteredCommand')
# 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()
# @param Event e
func _input(e):
if Input.is_action_just_pressed(action_console_toggle):
get_tree().paused = !get_tree().paused
toggleConsole()
# Show prev line in history
if Input.is_action_just_pressed(action_history_up):
_currCmd = _History.prev()
if _currCmdHandler == null:
_currCmdHandler = _consoleLine.text
# 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
# 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()
# 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()
# @param string url
func _handleUrlClick(url): # void
_setConsoleLine(url + ' ')
# @param string text
# @param bool moveCaretToEnd
func _setConsoleLine(text, moveCaretToEnd = true): # void
_consoleLine.text = text
_consoleLine.grab_focus()
if moveCaretToEnd:
_consoleLine.caret_position = text.length()
# @param string alias
# @param Dictionary params
func register(alias, params): # int
return _Commands.register(alias, params)
# @param string alias
func unregister(alias): # int
return _Commands.unregister(alias)
# @param string message
func write(message): # void
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)
_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')
isConsoleShown = !isConsoleShown
func _toggleAnimationFinished(animation): # void
if !isConsoleShown:
_consoleBox.hide()
func _setProtected(value): # void
Log.warn('Trying to set a protected variable, ignoring. Provided ' + str(value), \
'Console: _setProtected')