Initial Project Upload
This commit is contained in:
commit
37f8656620
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Normalize EOL for all files that Git considers text files.
|
||||||
|
* text=auto eol=lf
|
||||||
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Godot 4+ specific ignores
|
||||||
|
.godot/
|
||||||
|
/android/
|
||||||
4
source/.editorconfig
Normal file
4
source/.editorconfig
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 460 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 194 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 120 KiB |
BIN
source/addons/bbcode_edit.editor/.assets_for_readme/snippet.gif
Normal file
BIN
source/addons/bbcode_edit.editor/.assets_for_readme/snippet.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
21
source/addons/bbcode_edit.editor/LICENCE.txt
Normal file
21
source/addons/bbcode_edit.editor/LICENCE.txt
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 Patou
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
114
source/addons/bbcode_edit.editor/README.md
Normal file
114
source/addons/bbcode_edit.editor/README.md
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
# BBCodeEdit (for script editor[^editor_only])
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
A Godot addon that brings BBCode completion and QOL tools to the script editor
|
||||||
|
in order to help format documentation comments.
|
||||||
|
(May be extended to any CodeEdit in the future.[^editor_only])
|
||||||
|
|
||||||
|
|
||||||
|
# Showcase
|
||||||
|
|
||||||
|
There are **shortcuts** to easily toggle some formattings:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
**Completion** for formatting tags, with some special completions implemented for specific tags:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
**Documentation references** are completed:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
Some useful **snippets** are included:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
# Features / Roadmap
|
||||||
|
|
||||||
|
*Checked items are the implemented ones, unchecked are the ones in development.[^editor_only]*
|
||||||
|
|
||||||
|
- [ ] Code completion for:
|
||||||
|
- [x] Most used BBCode tags
|
||||||
|
- [ ] All BBCode tags[^editor_only] (See [Godot Reference](https://docs.godotengine.org/en/4.3/tutorials/ui/bbcode_in_richtextlabel.html#reference))
|
||||||
|
- [x] Documentation comments:
|
||||||
|
- [x] formatting tags
|
||||||
|
- [x] referencing tag
|
||||||
|
- [x] `@` tags:
|
||||||
|
- [x] deprecated
|
||||||
|
- [x] experimental
|
||||||
|
- [x] tutorial
|
||||||
|
- [x] Snippets:
|
||||||
|
- [x] **Note:**, **Warning:**...
|
||||||
|
- [ ] Classify tags accepted in documentation comments according to [Godot Reference](https://docs.godotengine.org/en/4.3/tutorials/scripting/gdscript/gdscript_documentation_comments.html#bbcode-and-class-reference)
|
||||||
|
- [ ] Advanced completions:
|
||||||
|
- [x] Color:
|
||||||
|
- [x] Named colors
|
||||||
|
- [x] Hexadecimal color preview (**Note: ** If it starts with a digit, `0x` will be prefixed temporarily because Godot cancels int completion)
|
||||||
|
- [x] Color picker
|
||||||
|
- [ ] URL of files? (I don't know if file URLs work)
|
||||||
|
- [x] Documentation comments' references: (NB: [Inner classes](https://docs.godotengine.org/en/4.3/tutorials/scripting/gdscript/gdscript_basics.html#inner-classes) won't be properly proposed in completions)
|
||||||
|
- [x] Classes
|
||||||
|
- [x] Parameters
|
||||||
|
- [x] Members (aka. Properties)
|
||||||
|
- [x] Methods (aka. Functions)
|
||||||
|
- [x] Constants
|
||||||
|
- [x] Signals
|
||||||
|
- [x] Enums
|
||||||
|
- [ ] Other references, like annotations or operators, are not implemented because they are rarely used.
|
||||||
|
- [ ] ~~BBCode preview (through [SyntaxHighlighter](https://docs.godotengine.org/en/4.3/classes/class_syntaxhighlighter.html)?)~~\
|
||||||
|
~~Edit: Won't work because GDSCriptSyntaxHighlighter can't be extended\
|
||||||
|
BBCode spellcheck/semi-preview (through `_draw()` ?)~~\
|
||||||
|
Edit 2: Won't implement, because there is easier:
|
||||||
|
- [ ] Add a shortcut to open:
|
||||||
|
- [x] Current file documentation (May have a problem if pressed before the editor checks unsaved status of the file)
|
||||||
|
- [ ] Preview of the selected text (or autodetect start and end if no selection)
|
||||||
|
- [ ] Add shortcuts for:
|
||||||
|
*You can rebind them in `Project → Project settings → Input Map`. If you just enabled the addon, they may appear here only after a restart of the editor. You will have to restart the editor for any change to take effect.*
|
||||||
|
- [x] **bold** (`alt + B`)
|
||||||
|
- [x] *italic* (`alt + I`)
|
||||||
|
- [x] ~~striketrough~~ (`alt + C`, but if you had unbound `alt + S` from `open shader editor`, it will be `alt + S`)
|
||||||
|
- [x] <u>underline</u> (`alt + U`)
|
||||||
|
- [ ] Wrap in any tag?
|
||||||
|
- [ ] Add an external CodeEdit in the editor to write bbcode, because completion inside strings is a nightmare due to builtin behaviors.[^editor_only]
|
||||||
|
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
You can download the addon:
|
||||||
|
- On GitHub: `Code` → `Download ZIP`.
|
||||||
|
- Through the editor: `AssetLib` → Search for "BBCodeEdit"
|
||||||
|
|
||||||
|
*By default, this readme is included, along with it's illustrations. If you don't want them,
|
||||||
|
do not download `addons/bbcode_edit.editor/README.md` nor `addons/bbcode_edit.editor/.assets_for_readme/*`*
|
||||||
|
|
||||||
|
To edit shortcuts:
|
||||||
|
- *If they don't show up* in the input map GUI: first restart the editor
|
||||||
|
- modify them in the input map GUI
|
||||||
|
- **restart** the editor to update the input map.
|
||||||
|
|
||||||
|
You can also exclude `*.editor/*` or `bbcode_edit.editor/` from your export presets,
|
||||||
|
because this addon is (for now[^editor_only]) script-editor-only.
|
||||||
|
|
||||||
|
|
||||||
|
## Godot version
|
||||||
|
|
||||||
|
Godot 4.3 (May work with previous 4.x versions)
|
||||||
|
|
||||||
|
|
||||||
|
# Development Status
|
||||||
|
|
||||||
|
Development halted. But the addon is really handy as-is.
|
||||||
|
|
||||||
|
[^editor_only]: **Note:** All non-script-editor-related features are on hold for now
|
||||||
|
because I don't have the time nor the need to implement them.
|
||||||
|
This would also require refactoring `bbcode_edit.gd` into two separate classes.
|
||||||
|
One with all [RichTextLabel's tags](https://docs.godotengine.org/en/4.3/tutorials/ui/bbcode_in_richtextlabel.html#reference)
|
||||||
|
and one with [documentation comments' tags](https://docs.godotengine.org/en/4.3/tutorials/scripting/gdscript/gdscript_documentation_comments.html#bbcode-and-class-reference).
|
||||||
|
If you really need BBCode completion in a CodeEdit (eg. for an inspector plugin, or for any code edit within an exported project),
|
||||||
|
I *may* give it a try, or you could contribute this refactor (this repo is under the MIT Licence).
|
||||||
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="20px" viewBox="0 -960 960 960" width="20px" fill="#e0e0e0"><path d="M456-96q-29.7 0-50.85-21.15Q384-138.3 384-168v-167H264q-29.7 0-50.85-21.15Q192-377.3 192-407v-265q0-61 42-102.5T336-816h432v409q0 29.7-21.5 50.85Q725-335 696-335H576v167q0 29.7-21.5 50.85Q533-96 504-96h-48ZM264-552h432v-192h-48v144h-72v-144h-48v73h-72v-73H336q-29.7 0-50.85 20.5Q264-703 264-672v120Zm0 145h432v-73H264v73Zm0 0v-73 73Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 458 B |
@ -0,0 +1,38 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bpwcspqlqm78h"
|
||||||
|
path="res://.godot/imported/bbcode_completion_icon.svg-e050b1e9fb923c5a17b0f52532042234.ctex"
|
||||||
|
metadata={
|
||||||
|
"has_editor_variant": true,
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://addons/bbcode_edit.editor/bbcode_completion_icon.svg"
|
||||||
|
dest_files=["res://.godot/imported/bbcode_completion_icon.svg-e050b1e9fb923c5a17b0f52532042234.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
|
svg/scale=1.0
|
||||||
|
editor/scale_with_editor_scale=true
|
||||||
|
editor/convert_colors_with_editor_theme=true
|
||||||
891
source/addons/bbcode_edit.editor/bbcode_edit.gd
Normal file
891
source/addons/bbcode_edit.editor/bbcode_edit.gd
Normal file
@ -0,0 +1,891 @@
|
|||||||
|
@tool
|
||||||
|
extends CodeEdit
|
||||||
|
|
||||||
|
|
||||||
|
enum CompletionKind {
|
||||||
|
IGNORE,
|
||||||
|
FORMATTING,
|
||||||
|
COLOR,
|
||||||
|
COMMAND,
|
||||||
|
CLASS_REFERENCE,
|
||||||
|
REFERENCE_START,
|
||||||
|
REFERENCE_END,
|
||||||
|
REFERENCING_TAG,
|
||||||
|
ANNOTATION,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Completions = preload("res://addons/bbcode_edit.editor/completions_db/completions.gd")
|
||||||
|
const Scraper = preload("res://addons/bbcode_edit.editor/editor_interface_scraper.gd")
|
||||||
|
|
||||||
|
const ACTION_TOGGLE_BOLD = &"bbcode_edit/toggle_bold"
|
||||||
|
const ACTION_TOGGLE_ITALIC = &"bbcode_edit/toggle_italic"
|
||||||
|
const ACTION_TOGGLE_UNDERLINE = &"bbcode_edit/toggle_underline"
|
||||||
|
const ACTION_TOGGLE_STRIKE = &"bbcode_edit/toggle_strike"
|
||||||
|
|
||||||
|
const TOGGLING_ACTIONS = {
|
||||||
|
ACTION_TOGGLE_BOLD: "b",
|
||||||
|
ACTION_TOGGLE_ITALIC: "i",
|
||||||
|
ACTION_TOGGLE_UNDERLINE: "u",
|
||||||
|
ACTION_TOGGLE_STRIKE: "s",
|
||||||
|
}
|
||||||
|
|
||||||
|
const BBCODE_COMPLETION_ICON = preload("res://addons/bbcode_edit.editor/bbcode_completion_icon.svg")
|
||||||
|
const COLOR_PICKER_CONTAINER_PATH = ^"_BBCodeEditColorPicker"
|
||||||
|
const COLOR_PICKER_PATH = ^"_BBCodeEditColorPicker/ColorPicker"
|
||||||
|
|
||||||
|
const MALFORMED = "MALFORMED"
|
||||||
|
const COMMAND_PREFIX_CHAR = "\u0001"
|
||||||
|
const ORDER_PREFIX = "\ufffe"
|
||||||
|
const CLASS_REFERENCE_PREFIX_CHAR = "\uffff"
|
||||||
|
const REFERENCE_START_SUFFIX_CHAR = "\uffff"
|
||||||
|
const REFERENCE_END_SUFFIX_CHAR = "\ufffe"
|
||||||
|
const ANNOTATION_SUFFIX_CHAR = "\ufff0"
|
||||||
|
const _COMMAND_COLOR_PICKER = "color_picker"
|
||||||
|
|
||||||
|
const CLASS_DOC_ENDERS: Array[String] = [
|
||||||
|
"##",
|
||||||
|
"signal",
|
||||||
|
"enum",
|
||||||
|
"const",
|
||||||
|
"@export",
|
||||||
|
"var",
|
||||||
|
"@onready",
|
||||||
|
"static",
|
||||||
|
"func",
|
||||||
|
"class ",
|
||||||
|
]
|
||||||
|
|
||||||
|
static var REGEX_PARENTHESES = RegEx.create_from_string(r"\(([^)]+)\)")
|
||||||
|
|
||||||
|
|
||||||
|
func _init() -> void:
|
||||||
|
set_process_input(true)
|
||||||
|
if has_meta(&"initialized"):
|
||||||
|
return
|
||||||
|
code_completion_requested.connect(add_completion_options)
|
||||||
|
text_changed.connect(_on_text_changed)
|
||||||
|
code_completion_prefixes += ["["] # Use assignation because append don't work
|
||||||
|
set_meta(&"initialized", true)
|
||||||
|
|
||||||
|
|
||||||
|
func add_completion_options() -> void:
|
||||||
|
#print("Code completion options requested")
|
||||||
|
var line_i: int = get_caret_line()
|
||||||
|
var line: String = get_line(line_i)
|
||||||
|
var column_i: int = get_caret_column()
|
||||||
|
var comment_i: int = is_in_comment(line_i, column_i)
|
||||||
|
|
||||||
|
if comment_i == -1 or get_delimiter_start_key(comment_i) != "##":
|
||||||
|
if line[column_i-1] == "[":
|
||||||
|
#print_rich("[color=red]Emergency cancel[/color]")
|
||||||
|
cancel_code_completion()
|
||||||
|
#print_rich("[color=red]not in bbcode completion[/color]")
|
||||||
|
return
|
||||||
|
#print_rich("[color=red]in bbcode completion[/color]")
|
||||||
|
|
||||||
|
var to_test: String = trim_doc_comment_start(line.left(column_i))
|
||||||
|
var line_only: String = to_test
|
||||||
|
|
||||||
|
if line_only[0] == "@" and not (
|
||||||
|
line_only.begins_with("@tutorial: ")
|
||||||
|
or line_only.begins_with("@deprecated: ")
|
||||||
|
or line_only.begins_with("@experimental: ")
|
||||||
|
):
|
||||||
|
add_code_completion_option(
|
||||||
|
CodeEdit.KIND_PLAIN_TEXT,
|
||||||
|
"@deprecated" + ANNOTATION_SUFFIX_CHAR,
|
||||||
|
"deprecated\n## ",
|
||||||
|
get_theme_color(&"font-color"),
|
||||||
|
Scraper.get_icon(&"StatusError"),
|
||||||
|
)
|
||||||
|
add_code_completion_option(
|
||||||
|
CodeEdit.KIND_PLAIN_TEXT,
|
||||||
|
"@deprecated: Some explaination" + ANNOTATION_SUFFIX_CHAR,
|
||||||
|
"deprecated: ",
|
||||||
|
get_theme_color(&"font-color"),
|
||||||
|
Scraper.get_icon(&"StatusError"),
|
||||||
|
)
|
||||||
|
add_code_completion_option(
|
||||||
|
CodeEdit.KIND_PLAIN_TEXT,
|
||||||
|
"@experimental" + ANNOTATION_SUFFIX_CHAR,
|
||||||
|
"experimental\n## ",
|
||||||
|
get_theme_color(&"font-color"),
|
||||||
|
Scraper.get_icon(&"NodeWarning"),
|
||||||
|
)
|
||||||
|
add_code_completion_option(
|
||||||
|
CodeEdit.KIND_PLAIN_TEXT,
|
||||||
|
"@experimental: Some explaination" + ANNOTATION_SUFFIX_CHAR,
|
||||||
|
"experimental: ",
|
||||||
|
get_theme_color(&"font-color"),
|
||||||
|
Scraper.get_icon(&"NodeWarning"),
|
||||||
|
)
|
||||||
|
|
||||||
|
var class_comment_end_line: int = 0
|
||||||
|
while not _is_line_class_doc_ender(get_line(class_comment_end_line)):
|
||||||
|
class_comment_end_line += 1
|
||||||
|
while get_line(class_comment_end_line).begins_with("##"):
|
||||||
|
class_comment_end_line += 1
|
||||||
|
if _is_line_class_doc_ender(get_line(class_comment_end_line)):
|
||||||
|
class_comment_end_line = -1
|
||||||
|
|
||||||
|
if line_i < class_comment_end_line:
|
||||||
|
add_code_completion_option(
|
||||||
|
CodeEdit.KIND_PLAIN_TEXT,
|
||||||
|
"@tutorial: https://example.com" + ANNOTATION_SUFFIX_CHAR,
|
||||||
|
"tutorial: https://",
|
||||||
|
get_theme_color(&"font-color"),
|
||||||
|
Scraper.get_icon(&"ExternalLink"),
|
||||||
|
)
|
||||||
|
add_code_completion_option(
|
||||||
|
CodeEdit.KIND_PLAIN_TEXT,
|
||||||
|
"@tutorial(Title): https://example.com" + ANNOTATION_SUFFIX_CHAR,
|
||||||
|
"tutorial(|): https://",
|
||||||
|
get_theme_color(&"font-color"),
|
||||||
|
Scraper.get_icon(&"ExternalLink"),
|
||||||
|
)
|
||||||
|
|
||||||
|
update_code_completion_options(true)
|
||||||
|
return
|
||||||
|
|
||||||
|
var prev_line_i: int = line_i - 1
|
||||||
|
var prev_line: String = get_line(prev_line_i).strip_edges(true, false)
|
||||||
|
while prev_line.begins_with("##"):
|
||||||
|
to_test = prev_line.trim_prefix("##").strip_edges() + " " + to_test
|
||||||
|
prev_line_i -= 1
|
||||||
|
prev_line = get_line(prev_line_i).strip_edges(true, false)
|
||||||
|
|
||||||
|
to_test = to_test.split("]")[-1]#.split("=")[-1]
|
||||||
|
#print_rich("to_test:[color=magenta][code] ", to_test)
|
||||||
|
|
||||||
|
if "[" not in to_test:
|
||||||
|
#print("No BRACKET")
|
||||||
|
update_code_completion_options(true)
|
||||||
|
return
|
||||||
|
|
||||||
|
var describes_i: int = line_i
|
||||||
|
while is_in_comment(describes_i) != -1:
|
||||||
|
describes_i += 1
|
||||||
|
var describes: String = get_line(describes_i)
|
||||||
|
|
||||||
|
if check_parameter_completions(to_test, describes_i, describes):
|
||||||
|
return
|
||||||
|
|
||||||
|
var font_color: Color = get_theme_color(&"font_color")
|
||||||
|
|
||||||
|
if line_only[0] == "[":
|
||||||
|
add_code_completion_option(
|
||||||
|
CodeEdit.KIND_PLAIN_TEXT,
|
||||||
|
"Note:",
|
||||||
|
"b]Note:[/b] ",
|
||||||
|
font_color,
|
||||||
|
Scraper.get_icon(&"TextMesh"),
|
||||||
|
)
|
||||||
|
add_code_completion_option(
|
||||||
|
CodeEdit.KIND_PLAIN_TEXT,
|
||||||
|
"Warning:",
|
||||||
|
"b]Warning:[/b] ",
|
||||||
|
font_color,
|
||||||
|
Scraper.get_icon(&"TextMesh"),
|
||||||
|
)
|
||||||
|
add_code_completion_option(
|
||||||
|
CodeEdit.KIND_PLAIN_TEXT,
|
||||||
|
"Example:",
|
||||||
|
"b]Example:[/b] ",
|
||||||
|
font_color,
|
||||||
|
Scraper.get_icon(&"TextMesh"),
|
||||||
|
)
|
||||||
|
|
||||||
|
# TODO only propose valid tags
|
||||||
|
var completions: Array[String] = (
|
||||||
|
Completions.TAGS_UNIVERSAL
|
||||||
|
+ Completions.TAGS_DOC_COMMENT_FORMATTING
|
||||||
|
# TODO MAYBE: I have to refactor everything related to tag availability.
|
||||||
|
#+ Completions.TAGS_RICH_TEXT_LABEL
|
||||||
|
)
|
||||||
|
var displays: Array[String] = []
|
||||||
|
displays.assign(completions.map(_bracket))
|
||||||
|
|
||||||
|
#print("First completion is: ", completions[0])
|
||||||
|
|
||||||
|
for i in completions.size():
|
||||||
|
add_code_completion_option(
|
||||||
|
CodeEdit.KIND_PLAIN_TEXT,
|
||||||
|
displays[i].replace("|", ""),
|
||||||
|
completions[i],
|
||||||
|
font_color,
|
||||||
|
BBCODE_COMPLETION_ICON,
|
||||||
|
)
|
||||||
|
|
||||||
|
var reference_completions: Array[String] = Completions.TAGS_DOC_COMMENT_REFERENCE
|
||||||
|
var reference_displays: Array[String] = []
|
||||||
|
for completion in reference_completions:
|
||||||
|
reference_displays.append(_bracket(completion.trim_suffix("|") + "Class.name"))
|
||||||
|
|
||||||
|
var reference_icon: Texture2D = Scraper.get_reference_icon()
|
||||||
|
for i in reference_completions.size():
|
||||||
|
add_code_completion_option(
|
||||||
|
CodeEdit.KIND_PLAIN_TEXT,
|
||||||
|
reference_displays[i].replace("|", ""),
|
||||||
|
reference_completions[i],
|
||||||
|
font_color,
|
||||||
|
reference_icon,
|
||||||
|
)
|
||||||
|
|
||||||
|
if describes.begins_with("func "):
|
||||||
|
add_code_completion_option(
|
||||||
|
CodeEdit.KIND_PLAIN_TEXT,
|
||||||
|
"[param name]",
|
||||||
|
"param |",
|
||||||
|
font_color,
|
||||||
|
reference_icon,
|
||||||
|
)
|
||||||
|
|
||||||
|
var class_completions := Completions.get_class_completions()
|
||||||
|
for i in len(class_completions.names):
|
||||||
|
var name_: String = class_completions.names[i]
|
||||||
|
add_code_completion_option(
|
||||||
|
CodeEdit.KIND_CLASS,
|
||||||
|
CLASS_REFERENCE_PREFIX_CHAR + "[" + name_ + "]",
|
||||||
|
name_ + "||",
|
||||||
|
font_color,
|
||||||
|
class_completions.icons[i],
|
||||||
|
)
|
||||||
|
|
||||||
|
update_code_completion_options(true) # NEEDED so that `[` triggers popup
|
||||||
|
|
||||||
|
|
||||||
|
func _is_line_class_doc_ender(line: String) -> bool:
|
||||||
|
for doc_ender in CLASS_DOC_ENDERS:
|
||||||
|
if line.begins_with(doc_ender):
|
||||||
|
return true
|
||||||
|
return false
|
||||||
|
|
||||||
|
|
||||||
|
func _bracket(string: String) -> String:
|
||||||
|
return "[" + string + "]"
|
||||||
|
|
||||||
|
|
||||||
|
func trim_doc_comment_start(line: String) -> String:
|
||||||
|
return line.strip_edges(true, false).trim_prefix("##").strip_edges(true, false)
|
||||||
|
|
||||||
|
|
||||||
|
func check_parameter_completions(to_test: String, describes_i: int, describes: String) -> bool:
|
||||||
|
to_test = to_test.split("[")[-1]
|
||||||
|
var parts: PackedStringArray = to_test.split(" ", false)
|
||||||
|
|
||||||
|
var parameters: PackedStringArray = PackedStringArray()
|
||||||
|
var values: PackedStringArray = PackedStringArray()
|
||||||
|
for part in parts:
|
||||||
|
# TODO MAYBE impleement sub parameter handling ? (e.g. [font otv="wght=200,wdth=400"])
|
||||||
|
var split: PackedStringArray = part.split("=", 1)
|
||||||
|
parameters.append(split[0])
|
||||||
|
values.append(split[1] if split.size() == 2 else MALFORMED)
|
||||||
|
|
||||||
|
#print_rich("Parameters:[color=magenta] ", parameters)
|
||||||
|
#print_rich("Values:[color=magenta] ", values)
|
||||||
|
|
||||||
|
if parameters.is_empty():
|
||||||
|
return false
|
||||||
|
|
||||||
|
if parameters.size() == 1 and values[0] != "MALFORMED":
|
||||||
|
var value: String = values[0]
|
||||||
|
match parameters[0]:
|
||||||
|
"color":
|
||||||
|
if value.begins_with(HEX_PREFIX) and value.substr(HEX_PREFIX.length()).is_valid_html_color():
|
||||||
|
add_hex_color(value.substr(HEX_PREFIX.length()), true)
|
||||||
|
elif value.is_valid_html_color():
|
||||||
|
if value.is_valid_int():
|
||||||
|
insert_text(HEX_PREFIX, get_caret_line(), get_caret_column()-value.length())
|
||||||
|
request_code_completion.call_deferred(true)
|
||||||
|
add_hex_color(value)
|
||||||
|
|
||||||
|
add_color_completions(value.length())
|
||||||
|
return true
|
||||||
|
|
||||||
|
match parameters[0]:
|
||||||
|
"param":
|
||||||
|
if not describes.begins_with("func "):
|
||||||
|
return false
|
||||||
|
|
||||||
|
if ")" not in describes:
|
||||||
|
var next_line_i: int = describes_i + 1
|
||||||
|
var next_line: String = get_line(next_line_i)
|
||||||
|
while ")" not in next_line:
|
||||||
|
describes += next_line
|
||||||
|
next_line_i += 1
|
||||||
|
next_line = get_line(next_line_i)
|
||||||
|
describes += next_line
|
||||||
|
#print_rich("Describes: [color=purple][code]", describes)
|
||||||
|
|
||||||
|
for part in (
|
||||||
|
REGEX_PARENTHESES.search(describes).get_string().trim_prefix("(").trim_suffix(")").split(",")
|
||||||
|
):
|
||||||
|
var param_parts := part.split(":", true, 1)
|
||||||
|
var parameter: String = param_parts[0].strip_edges()
|
||||||
|
|
||||||
|
add_code_completion_option(
|
||||||
|
CodeEdit.KIND_PLAIN_TEXT,
|
||||||
|
parameter + REFERENCE_END_SUFFIX_CHAR,
|
||||||
|
parameter + "||",
|
||||||
|
get_theme_color(&"font_color"),
|
||||||
|
Scraper.get_icon(&"Variant")
|
||||||
|
if param_parts.size() == 1 else
|
||||||
|
Scraper.try_get_icon(param_parts[1].split("=", true, 1)[0].strip_edges(), &"Variant")
|
||||||
|
)
|
||||||
|
|
||||||
|
update_code_completion_options(true)
|
||||||
|
return true
|
||||||
|
"member":
|
||||||
|
if parameters.size() >= 2:
|
||||||
|
var path: PackedStringArray = parameters[1].split(".")
|
||||||
|
if path.size() >= 2:
|
||||||
|
if ClassDB.class_exists(path[0]):
|
||||||
|
add_member_completion_from_class_name(path[0])
|
||||||
|
else:
|
||||||
|
for other_class_ in ProjectSettings.get_global_class_list():
|
||||||
|
if other_class_["class"] == path[0]:
|
||||||
|
add_member_completion_from_script(load(other_class_["path"]))
|
||||||
|
break
|
||||||
|
update_code_completion_options(true)
|
||||||
|
return true
|
||||||
|
add_member_completion_from_script(EditorInterface.get_script_editor().get_current_script())
|
||||||
|
add_classes_completion()
|
||||||
|
return true
|
||||||
|
"method":
|
||||||
|
if parameters.size() >= 2:
|
||||||
|
var path: PackedStringArray = parameters[1].split(".")
|
||||||
|
if path.size() >= 2:
|
||||||
|
if ClassDB.class_exists(path[0]):
|
||||||
|
add_method_completion_from_class_name(path[0])
|
||||||
|
else:
|
||||||
|
for other_class_ in ProjectSettings.get_global_class_list():
|
||||||
|
if other_class_["class"] == path[0]:
|
||||||
|
add_method_completion_from_script(load(other_class_["path"]))
|
||||||
|
break
|
||||||
|
update_code_completion_options(true)
|
||||||
|
return true
|
||||||
|
add_method_completion_from_script(EditorInterface.get_script_editor().get_current_script())
|
||||||
|
add_classes_completion()
|
||||||
|
return true
|
||||||
|
"constant":
|
||||||
|
if parameters.size() >= 2:
|
||||||
|
var path: PackedStringArray = parameters[1].split(".")
|
||||||
|
if path.size() >= 2:
|
||||||
|
if ClassDB.class_exists(path[0]):
|
||||||
|
add_constant_completion_from_class_name(path[0])
|
||||||
|
else:
|
||||||
|
for other_class_ in ProjectSettings.get_global_class_list():
|
||||||
|
if other_class_["class"] == path[0]:
|
||||||
|
add_constant_completion_from_script(load(other_class_["path"]))
|
||||||
|
break
|
||||||
|
update_code_completion_options(true)
|
||||||
|
return true
|
||||||
|
add_constant_completion_from_script(EditorInterface.get_script_editor().get_current_script())
|
||||||
|
add_classes_completion()
|
||||||
|
return true
|
||||||
|
"signal":
|
||||||
|
if parameters.size() >= 2:
|
||||||
|
var path: PackedStringArray = parameters[1].split(".")
|
||||||
|
if path.size() >= 2:
|
||||||
|
if ClassDB.class_exists(path[0]):
|
||||||
|
add_signal_completion_from_class_name(path[0])
|
||||||
|
else:
|
||||||
|
for other_class_ in ProjectSettings.get_global_class_list():
|
||||||
|
if other_class_["class"] == path[0]:
|
||||||
|
add_signal_completion_from_script(load(other_class_["path"]))
|
||||||
|
break
|
||||||
|
update_code_completion_options(true)
|
||||||
|
return true
|
||||||
|
add_signal_completion_from_script(EditorInterface.get_script_editor().get_current_script())
|
||||||
|
add_classes_completion()
|
||||||
|
return true
|
||||||
|
"enum":
|
||||||
|
if parameters.size() >= 2:
|
||||||
|
var path: PackedStringArray = parameters[1].split(".")
|
||||||
|
if path.size() >= 2:
|
||||||
|
if ClassDB.class_exists(path[0]):
|
||||||
|
add_enum_completion_from_class_name(path[0])
|
||||||
|
else:
|
||||||
|
for other_class_ in ProjectSettings.get_global_class_list():
|
||||||
|
if other_class_["class"] == path[0]:
|
||||||
|
add_enum_completion_from_script(load(other_class_["path"]))
|
||||||
|
break
|
||||||
|
update_code_completion_options(true)
|
||||||
|
return true
|
||||||
|
add_enum_completion_from_script(EditorInterface.get_script_editor().get_current_script())
|
||||||
|
add_classes_completion()
|
||||||
|
return true
|
||||||
|
|
||||||
|
return false
|
||||||
|
|
||||||
|
|
||||||
|
func substr_clamped_start(string: String, from: int, len: int) -> String:
|
||||||
|
if from < 0:
|
||||||
|
if len != -1:
|
||||||
|
len += from
|
||||||
|
if len < 0:
|
||||||
|
len = 0
|
||||||
|
from = 0
|
||||||
|
|
||||||
|
return string.substr(from, len)
|
||||||
|
|
||||||
|
|
||||||
|
const HEX_PREFIX = "0x"
|
||||||
|
func add_hex_color(hex: String, include_prefix: bool = false) -> void:
|
||||||
|
print_rich("Valid color: ", hex, " [color=", hex, "]██████")
|
||||||
|
add_code_completion_option(
|
||||||
|
CodeEdit.KIND_PLAIN_TEXT,
|
||||||
|
HEX_PREFIX + hex + " ",
|
||||||
|
HEX_PREFIX + hex if include_prefix else hex,
|
||||||
|
get_theme_color(&"font_color"),
|
||||||
|
Scraper.get_color_icon(),
|
||||||
|
Color.html(hex),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func add_color_completions(chars_typed: int) -> void:
|
||||||
|
var icon = Scraper.get_color_icon()
|
||||||
|
for color in Completions.COLORS:
|
||||||
|
add_code_completion_option(
|
||||||
|
CodeEdit.KIND_PLAIN_TEXT,
|
||||||
|
color,
|
||||||
|
color,
|
||||||
|
get_theme_color(&"font_color"),
|
||||||
|
icon,
|
||||||
|
Color.from_string(color, Color.RED),
|
||||||
|
)
|
||||||
|
|
||||||
|
add_code_completion_option(
|
||||||
|
CodeEdit.KIND_PLAIN_TEXT,
|
||||||
|
COMMAND_PREFIX_CHAR + "Bring color picker",
|
||||||
|
_COMMAND_COLOR_PICKER + "," + str(chars_typed),
|
||||||
|
get_theme_color(&"font_color"),
|
||||||
|
EditorInterface.get_base_control().get_theme_icon("ColorPicker", "EditorIcons"),
|
||||||
|
)
|
||||||
|
update_code_completion_options(true)
|
||||||
|
|
||||||
|
|
||||||
|
## Add completion for classes WITH SUBSCRIPT (aka it will add a dot at the end)
|
||||||
|
func add_classes_completion() -> void:
|
||||||
|
var class_completions := Completions.get_class_completions()
|
||||||
|
for i in len(class_completions.names):
|
||||||
|
var name_: String = class_completions.names[i]
|
||||||
|
add_code_completion_option(
|
||||||
|
CodeEdit.KIND_CLASS,
|
||||||
|
ORDER_PREFIX + name_ + "." + REFERENCE_START_SUFFIX_CHAR,
|
||||||
|
name_ + ".",
|
||||||
|
get_theme_color(&"font_color"),
|
||||||
|
class_completions.icons[i],
|
||||||
|
)
|
||||||
|
update_code_completion_options(true)
|
||||||
|
|
||||||
|
|
||||||
|
func add_member_completion_from_script(class_: Script) -> void:
|
||||||
|
add_members(class_.get_script_property_list())
|
||||||
|
# Don't show inherited things, because the reference won't work.
|
||||||
|
#add_member_completion_from_class_name(class_.get_instance_base_type())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func add_member_completion_from_class_name(class_: StringName) -> void:
|
||||||
|
add_members(ClassDB.class_get_property_list(class_, true))
|
||||||
|
|
||||||
|
|
||||||
|
func add_members(members: Array[Dictionary]) -> void:
|
||||||
|
for member in members:
|
||||||
|
if member["usage"] & (
|
||||||
|
PROPERTY_USAGE_INTERNAL
|
||||||
|
| PROPERTY_USAGE_CATEGORY
|
||||||
|
| PROPERTY_USAGE_GROUP
|
||||||
|
| PROPERTY_USAGE_SUBGROUP
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
|
||||||
|
add_code_completion_option(
|
||||||
|
CodeEdit.KIND_MEMBER,
|
||||||
|
member["name"] + REFERENCE_END_SUFFIX_CHAR,
|
||||||
|
member["name"] + "||",
|
||||||
|
get_theme_color(&"font-color"),
|
||||||
|
get_icon_for_member(member),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func get_icon_for_member(member: Dictionary, fallback: StringName = &"MemberProperty") -> Texture2D:
|
||||||
|
if member["type"] == TYPE_OBJECT:
|
||||||
|
return Scraper.get_class_icon(member["class_name"], fallback)
|
||||||
|
|
||||||
|
return Scraper.get_builtin_type_icon(member["type"], fallback)
|
||||||
|
|
||||||
|
|
||||||
|
func add_method_completion_from_script(class_: Script) -> void:
|
||||||
|
add_methods(class_.get_method_list())
|
||||||
|
# Don't show inherited things, because the reference won't work.
|
||||||
|
#add_method_completion_from_class_name(class_.get_instance_base_type())
|
||||||
|
|
||||||
|
|
||||||
|
func add_method_completion_from_class_name(class_: StringName) -> void:
|
||||||
|
add_methods(ClassDB.class_get_method_list(class_, true))
|
||||||
|
|
||||||
|
|
||||||
|
func add_methods(methods: Array[Dictionary]) -> void:
|
||||||
|
for method in methods:
|
||||||
|
add_code_completion_option(
|
||||||
|
CodeEdit.KIND_FUNCTION,
|
||||||
|
method["name"] + REFERENCE_END_SUFFIX_CHAR,
|
||||||
|
method["name"] + "||",
|
||||||
|
get_theme_color(&"font-color"),
|
||||||
|
get_icon_for_method(method),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func get_icon_for_method(method: Dictionary) -> Texture2D:
|
||||||
|
var returned: Dictionary = method["return"]
|
||||||
|
|
||||||
|
if returned["type"] == TYPE_NIL:
|
||||||
|
return Scraper.get_icon(&"MemberMethod")
|
||||||
|
|
||||||
|
return get_icon_for_member(returned, &"Function")
|
||||||
|
|
||||||
|
|
||||||
|
func add_constant_completion_from_script(class_: Script) -> void:
|
||||||
|
add_constants(class_.get_script_constant_map())
|
||||||
|
# Don't show inherited things, because the reference won't work.
|
||||||
|
#add_constant_completion_from_class_name(class_.get_instance_base_type())
|
||||||
|
|
||||||
|
|
||||||
|
func add_constant_completion_from_class_name(class_: StringName) -> void:
|
||||||
|
for constant_name in ClassDB.class_get_integer_constant_list(class_, true):
|
||||||
|
add_constants({constant_name: ClassDB.class_get_integer_constant(class_, constant_name)})
|
||||||
|
|
||||||
|
|
||||||
|
func add_constants(constants: Dictionary) -> void:
|
||||||
|
for constant in constants:
|
||||||
|
var value: Variant = constants[constant]
|
||||||
|
var type: int = typeof(value)
|
||||||
|
|
||||||
|
if type == TYPE_OBJECT and value is Script and value.resource_path.is_empty():
|
||||||
|
# Inner classes don't work in class
|
||||||
|
continue
|
||||||
|
|
||||||
|
var display_text: String = constant
|
||||||
|
if type != TYPE_COLOR:
|
||||||
|
var repr: String = var_to_str(value)
|
||||||
|
if repr.is_empty():
|
||||||
|
if type == TYPE_OBJECT:
|
||||||
|
repr = value.to_string()
|
||||||
|
else:
|
||||||
|
repr = str(repr)
|
||||||
|
if repr.length() > 32:
|
||||||
|
repr = repr.left(32) + "..."
|
||||||
|
display_text += " (" + repr + ")"
|
||||||
|
display_text += REFERENCE_END_SUFFIX_CHAR
|
||||||
|
|
||||||
|
add_code_completion_option(
|
||||||
|
CodeEdit.KIND_CONSTANT,
|
||||||
|
display_text,
|
||||||
|
constant + "||",
|
||||||
|
get_theme_color(&"font-color"),
|
||||||
|
Scraper.get_type_icon(value, &"MemberConstant"),
|
||||||
|
value
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func add_signal_completion_from_script(class_: Script) -> void:
|
||||||
|
add_signals(class_.get_script_signal_list())
|
||||||
|
# Don't show inherited things, because the reference won't work.
|
||||||
|
#add_signal_completion_from_class_name(class_.get_instance_base_type())
|
||||||
|
|
||||||
|
|
||||||
|
func add_signal_completion_from_class_name(class_: StringName) -> void:
|
||||||
|
add_signals(ClassDB.class_get_signal_list(class_, true))
|
||||||
|
|
||||||
|
|
||||||
|
func add_signals(signals: Array[Dictionary]) -> void:
|
||||||
|
var icon: Texture2D = Scraper.get_icon(&"MemberSignal")
|
||||||
|
for signal_ in signals:
|
||||||
|
add_code_completion_option(
|
||||||
|
CodeEdit.KIND_SIGNAL,
|
||||||
|
signal_["name"] + REFERENCE_END_SUFFIX_CHAR,
|
||||||
|
signal_["name"] + "||",
|
||||||
|
get_theme_color(&"font-color"),
|
||||||
|
icon,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func add_enum_completion_from_script(class_: Script) -> void:
|
||||||
|
var map := class_.get_script_constant_map()
|
||||||
|
var probable_enums: PackedStringArray
|
||||||
|
|
||||||
|
for constant in map:
|
||||||
|
if typeof(map[constant]) == TYPE_DICTIONARY:
|
||||||
|
var candidate: Dictionary = map[constant]
|
||||||
|
if candidate.values().all(_is_int):
|
||||||
|
probable_enums.append(constant)
|
||||||
|
|
||||||
|
if probable_enums:
|
||||||
|
add_enums(probable_enums)
|
||||||
|
|
||||||
|
# Don't show inherited things, because the reference won't work.
|
||||||
|
#add_enum_completion_from_class_name(class_.get_instance_base_type())
|
||||||
|
|
||||||
|
|
||||||
|
static func _is_int(value: Variant) -> bool:
|
||||||
|
return typeof(value) == TYPE_INT
|
||||||
|
|
||||||
|
|
||||||
|
func add_enum_completion_from_class_name(class_: StringName) -> void:
|
||||||
|
add_enums(ClassDB.class_get_enum_list(class_, true))
|
||||||
|
|
||||||
|
|
||||||
|
func add_enums(enums: PackedStringArray) -> void:
|
||||||
|
var icon: Texture2D = Scraper.get_icon(&"Enum")
|
||||||
|
for enum_ in enums:
|
||||||
|
add_code_completion_option(
|
||||||
|
CodeEdit.KIND_ENUM,
|
||||||
|
enum_ + REFERENCE_END_SUFFIX_CHAR,
|
||||||
|
enum_ + "||",
|
||||||
|
get_theme_color(&"font-color"),
|
||||||
|
icon,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func toggle_tag(tag: String) -> void:
|
||||||
|
var prefix: String = "[" + tag + "]"
|
||||||
|
var prefix_len: int = prefix.length()
|
||||||
|
var suffix: String = "[/" + tag + "]"
|
||||||
|
var suffix_len: int = suffix.length()
|
||||||
|
|
||||||
|
var main_selection_from_column: int = get_selection_from_column()
|
||||||
|
var main_selection_from_line: int = get_selection_from_line()
|
||||||
|
var main_selection_to_column: int = get_selection_to_column()
|
||||||
|
var main_selection_to_line: int = get_selection_to_line()
|
||||||
|
var main_selection_end_line: String = get_line(main_selection_to_line)
|
||||||
|
|
||||||
|
if (
|
||||||
|
main_selection_from_column > prefix_len
|
||||||
|
and get_line(main_selection_from_line).substr(
|
||||||
|
main_selection_from_column - prefix_len,
|
||||||
|
prefix_len
|
||||||
|
) == prefix
|
||||||
|
and main_selection_to_column <= main_selection_end_line.length() - suffix_len
|
||||||
|
and main_selection_end_line.substr(
|
||||||
|
main_selection_to_column,
|
||||||
|
suffix_len
|
||||||
|
) == suffix
|
||||||
|
):
|
||||||
|
begin_complex_operation()
|
||||||
|
begin_multicaret_edit()
|
||||||
|
|
||||||
|
for caret in get_caret_count():
|
||||||
|
if multicaret_edit_ignore_caret(caret):
|
||||||
|
continue
|
||||||
|
|
||||||
|
var initial_text: String = get_selected_text(caret)
|
||||||
|
var initial_start_column: int = get_selection_from_column(caret)
|
||||||
|
var initial_end_column: int = get_selection_to_column(caret)
|
||||||
|
|
||||||
|
select(
|
||||||
|
get_selection_from_line(caret),
|
||||||
|
initial_start_column - prefix_len,
|
||||||
|
get_selection_to_line(caret),
|
||||||
|
initial_end_column + suffix_len,
|
||||||
|
caret
|
||||||
|
)
|
||||||
|
insert_text_at_caret(initial_text, caret)
|
||||||
|
select(
|
||||||
|
get_selection_from_line(caret),
|
||||||
|
initial_start_column - prefix_len,
|
||||||
|
get_selection_to_line(caret),
|
||||||
|
initial_end_column - prefix_len,
|
||||||
|
caret
|
||||||
|
)
|
||||||
|
|
||||||
|
end_multicaret_edit()
|
||||||
|
end_complex_operation()
|
||||||
|
return
|
||||||
|
|
||||||
|
begin_complex_operation()
|
||||||
|
begin_multicaret_edit()
|
||||||
|
|
||||||
|
for caret in get_caret_count():
|
||||||
|
if multicaret_edit_ignore_caret(caret):
|
||||||
|
continue
|
||||||
|
|
||||||
|
var initial_start_column: int = get_selection_from_column(caret)
|
||||||
|
var initial_end_column: int = get_selection_to_column(caret)
|
||||||
|
|
||||||
|
insert_text_at_caret(prefix + get_selected_text(caret) + suffix, caret)
|
||||||
|
|
||||||
|
select(
|
||||||
|
get_selection_from_line(caret),
|
||||||
|
initial_start_column + prefix_len,
|
||||||
|
get_selection_to_line(caret),
|
||||||
|
initial_end_column + prefix_len,
|
||||||
|
caret
|
||||||
|
)
|
||||||
|
|
||||||
|
end_multicaret_edit()
|
||||||
|
end_complex_operation()
|
||||||
|
|
||||||
|
|
||||||
|
func _confirm_code_completion(replace: bool = false) -> void:
|
||||||
|
var selected_completion: Dictionary = get_code_completion_option(get_code_completion_selected_index())
|
||||||
|
var display_text: String = selected_completion["display_text"]
|
||||||
|
var prefix: String = display_text[0]
|
||||||
|
|
||||||
|
if prefix == COMMAND_PREFIX_CHAR:
|
||||||
|
var parts: PackedStringArray = selected_completion["insert_text"].split(",")
|
||||||
|
var chars_to_remove: int = int(parts[1]) if parts.size() >= 2 else 0
|
||||||
|
if chars_to_remove:
|
||||||
|
for caret in get_caret_count():
|
||||||
|
var line_i: int = get_caret_line(caret)
|
||||||
|
var line: String = get_line(line_i)
|
||||||
|
var column_i: int = get_caret_column(caret)
|
||||||
|
set_line(line_i, line.left(column_i - chars_to_remove) + line.substr(column_i))
|
||||||
|
set_caret_column(column_i - chars_to_remove, false, caret)
|
||||||
|
|
||||||
|
match parts[0]:
|
||||||
|
_COMMAND_COLOR_PICKER:
|
||||||
|
if not has_node(^"BBCODE_EDIT_COLOR_PICKER"):
|
||||||
|
add_child(preload("res://addons/bbcode_edit.editor/color_picker.tscn").instantiate())
|
||||||
|
var container: PopupPanel = get_node(COLOR_PICKER_CONTAINER_PATH)
|
||||||
|
var picker: ColorPicker = get_node(COLOR_PICKER_PATH)
|
||||||
|
|
||||||
|
container.position = Vector2(get_pos_at_line_column(get_caret_line(), get_caret_column())) + global_position + Vector2(0, get_line_height())
|
||||||
|
container.add_theme_stylebox_override(&"panel", EditorInterface.get_base_control().get_theme_stylebox(&"Content", &"EditorStyles"))
|
||||||
|
picker.color_changed.connect(_on_color_picker_color_changed)
|
||||||
|
|
||||||
|
cancel_code_completion()
|
||||||
|
return
|
||||||
|
|
||||||
|
var icon: Texture2D = selected_completion["icon"]
|
||||||
|
var suffix: String = display_text[-1]
|
||||||
|
var kind: CompletionKind = (
|
||||||
|
CompletionKind.FORMATTING if icon == BBCODE_COMPLETION_ICON else
|
||||||
|
CompletionKind.COLOR if icon == Scraper.get_color_icon() else
|
||||||
|
CompletionKind.CLASS_REFERENCE if prefix == CLASS_REFERENCE_PREFIX_CHAR else
|
||||||
|
CompletionKind.REFERENCE_START if suffix == REFERENCE_START_SUFFIX_CHAR else
|
||||||
|
CompletionKind.REFERENCE_END if suffix == REFERENCE_END_SUFFIX_CHAR else
|
||||||
|
CompletionKind.ANNOTATION if suffix == ANNOTATION_SUFFIX_CHAR else
|
||||||
|
CompletionKind.REFERENCING_TAG if icon == Scraper.get_reference_icon() else
|
||||||
|
0
|
||||||
|
)
|
||||||
|
|
||||||
|
#print_rich("Kind is [color=red][code]", CompletionKind.find_key(kind))
|
||||||
|
|
||||||
|
begin_complex_operation()
|
||||||
|
|
||||||
|
# Don't use the following code, it's a dev crime.
|
||||||
|
# Oops, I just did...
|
||||||
|
# This code block allows to call the code that is meant to be executed
|
||||||
|
# when the virtual method isn't implemented.
|
||||||
|
var script: GDScript = get_script()
|
||||||
|
set_script(null)
|
||||||
|
super.confirm_code_completion(replace)
|
||||||
|
set_script(script)
|
||||||
|
|
||||||
|
if (
|
||||||
|
kind == CompletionKind.FORMATTING
|
||||||
|
or kind == CompletionKind.CLASS_REFERENCE
|
||||||
|
or kind == CompletionKind.REFERENCING_TAG
|
||||||
|
):
|
||||||
|
for caret in get_caret_count():
|
||||||
|
var line: String = get_line(get_caret_line(caret)) + " " # Add space so that column is in range
|
||||||
|
var column: int = get_caret_column(caret)
|
||||||
|
if not line[column] == "]":
|
||||||
|
insert_text_at_caret("]", caret)
|
||||||
|
# Replace caret at it's previous column
|
||||||
|
set_caret_column(column, false, caret)
|
||||||
|
|
||||||
|
if kind == CompletionKind.COLOR:
|
||||||
|
var line_i: int = get_caret_line()
|
||||||
|
var line: String = get_line(line_i)
|
||||||
|
var column: int = get_caret_column()
|
||||||
|
var color_start: int = column - selected_completion["display_text"].length() + 1
|
||||||
|
if line.substr(color_start).begins_with(HEX_PREFIX):
|
||||||
|
set_line(
|
||||||
|
line_i,
|
||||||
|
line.left(color_start) + line.substr(color_start + HEX_PREFIX.length())
|
||||||
|
)
|
||||||
|
set_caret_column(column - HEX_PREFIX.length())
|
||||||
|
|
||||||
|
for caret in get_caret_count():
|
||||||
|
set_caret_column(get_caret_column(caret) + 1, false, caret)
|
||||||
|
elif kind:
|
||||||
|
for caret in get_caret_count():
|
||||||
|
var line_i: int = get_caret_line(caret)
|
||||||
|
var line: String = get_line(line_i)
|
||||||
|
var first_pipe: int = line.find("|")
|
||||||
|
if first_pipe == -1: # Just in case
|
||||||
|
continue
|
||||||
|
var pipe_end: int = first_pipe + 1
|
||||||
|
while pipe_end < line.length() and line[pipe_end] == "|":
|
||||||
|
pipe_end += 1
|
||||||
|
set_line(line_i, line.left(first_pipe) + line.substr(pipe_end))
|
||||||
|
set_caret_column(pipe_end-1, false, caret)
|
||||||
|
|
||||||
|
end_complex_operation()
|
||||||
|
|
||||||
|
if kind == CompletionKind.REFERENCING_TAG:
|
||||||
|
var prefixes := code_completion_prefixes
|
||||||
|
code_completion_prefixes += [" "]
|
||||||
|
request_code_completion()
|
||||||
|
code_completion_prefixes = prefixes
|
||||||
|
elif kind and kind != CompletionKind.ANNOTATION:
|
||||||
|
request_code_completion()
|
||||||
|
|
||||||
|
|
||||||
|
func _gui_input(event: InputEvent) -> void:
|
||||||
|
if not event.is_pressed() or event.is_echo():
|
||||||
|
return
|
||||||
|
|
||||||
|
if has_node(COLOR_PICKER_CONTAINER_PATH):
|
||||||
|
if event is InputEventKey or event is InputEventMouseButton:
|
||||||
|
get_node(COLOR_PICKER_CONTAINER_PATH).free()
|
||||||
|
|
||||||
|
for action in TOGGLING_ACTIONS:
|
||||||
|
if is_action(event, action):
|
||||||
|
toggle_tag(TOGGLING_ACTIONS[action])
|
||||||
|
|
||||||
|
|
||||||
|
func is_action(event: InputEvent, action: StringName) -> bool:
|
||||||
|
return InputMap.has_action(action) and event.is_action(action, true)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_text_changed() -> void:
|
||||||
|
var line_i: int = get_caret_line()
|
||||||
|
var column_i: int = get_caret_column()
|
||||||
|
var line: String = get_line(get_caret_line())
|
||||||
|
if (
|
||||||
|
is_in_comment(line_i, column_i) == -1
|
||||||
|
and is_in_string(line_i, column_i) == -1
|
||||||
|
and line
|
||||||
|
and line[column_i-1] == "["
|
||||||
|
):
|
||||||
|
cancel_code_completion() # Prevent completing when typing array fast
|
||||||
|
|
||||||
|
|
||||||
|
func _on_color_picker_color_changed(color: Color) -> void:
|
||||||
|
var hex: String = color.to_html(color.a8 != 255)
|
||||||
|
|
||||||
|
for caret in get_caret_count():
|
||||||
|
var line_i: int = get_caret_line(caret)
|
||||||
|
var line: String = get_line(line_i)
|
||||||
|
var column_i: int = get_caret_column(caret)
|
||||||
|
|
||||||
|
if line[column_i] != "]" and line[column_i] != " ":
|
||||||
|
var to_scan: String = line.substr(column_i)
|
||||||
|
var end: int = to_scan.find("]")
|
||||||
|
|
||||||
|
if end == -1:
|
||||||
|
end = to_scan.find(" ")
|
||||||
|
else:
|
||||||
|
var other: int = to_scan.find(" ")
|
||||||
|
if other != -1 and other < end:
|
||||||
|
end = other
|
||||||
|
|
||||||
|
set_line(line_i, line.left(column_i) + to_scan.substr(end))
|
||||||
|
|
||||||
|
insert_text_at_caret(hex, caret)
|
||||||
|
set_caret_column(column_i, false, caret)
|
||||||
1
source/addons/bbcode_edit.editor/bbcode_edit.gd.uid
Normal file
1
source/addons/bbcode_edit.editor/bbcode_edit.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://3wc61yw7stvq
|
||||||
218
source/addons/bbcode_edit.editor/bbcode_edit_main.gd
Normal file
218
source/addons/bbcode_edit.editor/bbcode_edit_main.gd
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
@tool
|
||||||
|
extends EditorPlugin
|
||||||
|
|
||||||
|
|
||||||
|
const BBCodeEdit: GDScript = preload("res://addons/bbcode_edit.editor/bbcode_edit.gd")
|
||||||
|
const Scraper = preload("res://addons/bbcode_edit.editor/editor_interface_scraper.gd")
|
||||||
|
|
||||||
|
|
||||||
|
const ADDON_NAME = "BBCode Editor"
|
||||||
|
const ACTION_OPEN_DOC = &"bbcode_edit/editor/open_current_file_documentation"
|
||||||
|
const ACTION_SETTINGS: Array[StringName] = [
|
||||||
|
"input/" + ACTION_OPEN_DOC,
|
||||||
|
"input/" + BBCodeEdit.ACTION_TOGGLE_BOLD,
|
||||||
|
"input/" + BBCodeEdit.ACTION_TOGGLE_ITALIC,
|
||||||
|
"input/" + BBCodeEdit.ACTION_TOGGLE_UNDERLINE,
|
||||||
|
"input/" + BBCodeEdit.ACTION_TOGGLE_STRIKE,
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
func _enable_plugin() -> void:
|
||||||
|
print("Enabling ", ADDON_NAME)
|
||||||
|
add_keybinds()
|
||||||
|
_on_editor_startup.call_deferred()
|
||||||
|
print("Enabled ", ADDON_NAME)
|
||||||
|
|
||||||
|
|
||||||
|
func _disable_plugin() -> void:
|
||||||
|
print("Disabling ", ADDON_NAME)
|
||||||
|
for editor in EditorInterface.get_script_editor().get_open_script_editors():
|
||||||
|
editor.get_base_editor().set_script(null)
|
||||||
|
remove_keybinds()
|
||||||
|
for setting in ACTION_SETTINGS:
|
||||||
|
InputMap.erase_action(setting.substr(6))
|
||||||
|
print("Disabled ", ADDON_NAME)
|
||||||
|
|
||||||
|
|
||||||
|
func _enter_tree() -> void:
|
||||||
|
if not EditorInterface.has_meta(&"bbcode_edit_saved_once"):
|
||||||
|
EditorInterface.set_meta(&"bbcode_edit_saved_once", PackedStringArray())
|
||||||
|
_on_editor_startup.call_deferred()
|
||||||
|
|
||||||
|
|
||||||
|
var started_up: bool = false
|
||||||
|
func _on_editor_startup() -> void:
|
||||||
|
if started_up:
|
||||||
|
return
|
||||||
|
started_up = true
|
||||||
|
|
||||||
|
# TODO check if InputMap.load_from_project_settings() is better
|
||||||
|
for setting in ACTION_SETTINGS:
|
||||||
|
if !ProjectSettings.has_setting(setting):
|
||||||
|
continue
|
||||||
|
var action_dict: Dictionary = ProjectSettings.get_setting(setting)
|
||||||
|
var action_name: StringName = setting.substr(6)
|
||||||
|
InputMap.add_action(action_name, action_dict["deadzone"])
|
||||||
|
for event in action_dict["events"]:
|
||||||
|
InputMap.action_add_event(action_name, event)
|
||||||
|
|
||||||
|
EditorInterface.get_script_editor().editor_script_changed.connect(check_current.unbind(1))
|
||||||
|
check_current.call_deferred()
|
||||||
|
|
||||||
|
|
||||||
|
func add_keybinds() -> void:
|
||||||
|
var toggle_bold := InputEventKey.new()
|
||||||
|
toggle_bold.alt_pressed = true
|
||||||
|
toggle_bold.keycode = 66
|
||||||
|
ProjectSettings.set_setting(
|
||||||
|
&"input/bbcode_edit/toggle_bold",
|
||||||
|
{
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": [toggle_bold],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var toggle_italic := InputEventKey.new()
|
||||||
|
toggle_italic.alt_pressed = true
|
||||||
|
toggle_italic.keycode = 73
|
||||||
|
ProjectSettings.set_setting(
|
||||||
|
&"input/bbcode_edit/toggle_italic",
|
||||||
|
{
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": [toggle_italic],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var toggle_underline := InputEventKey.new()
|
||||||
|
toggle_underline.alt_pressed = true
|
||||||
|
toggle_underline.keycode = 85
|
||||||
|
ProjectSettings.set_setting(
|
||||||
|
&"input/bbcode_edit/toggle_underline",
|
||||||
|
{
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": [toggle_underline],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var toggle_strike := InputEventKey.new()
|
||||||
|
toggle_strike.alt_pressed = true
|
||||||
|
toggle_strike.keycode = _get_striketrough_keycode()
|
||||||
|
ProjectSettings.set_setting(
|
||||||
|
&"input/bbcode_edit/toggle_strike",
|
||||||
|
{
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": [toggle_strike],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if Engine.is_editor_hint():
|
||||||
|
add_editor_keybinds()
|
||||||
|
|
||||||
|
ProjectSettings.save()
|
||||||
|
print_rich("[color=orange]If you don't see the keybinds in the InputMap, please reload the Project.[/color]")
|
||||||
|
|
||||||
|
|
||||||
|
func _get_striketrough_keycode() -> int:
|
||||||
|
var editor_shortcuts: Variant = EditorInterface.get_editor_settings().get(&"shortcuts")
|
||||||
|
|
||||||
|
if editor_shortcuts == null:
|
||||||
|
return KEY_C
|
||||||
|
|
||||||
|
for shortcut: Dictionary in editor_shortcuts:
|
||||||
|
if shortcut["name"] == "bottom_panels/toggle_shader_editor_bottom_panel":
|
||||||
|
var input_events: Array = shortcut.get("shortcuts")
|
||||||
|
for input_event: InputEvent in input_events:
|
||||||
|
if input_event.keycode == KEY_S:
|
||||||
|
return KEY_C
|
||||||
|
return KEY_S
|
||||||
|
|
||||||
|
return KEY_C
|
||||||
|
|
||||||
|
|
||||||
|
func add_editor_keybinds() -> void:
|
||||||
|
var open_current_file_documentation := InputEventKey.new()
|
||||||
|
open_current_file_documentation.shift_pressed = true
|
||||||
|
open_current_file_documentation.keycode = 4194332
|
||||||
|
ProjectSettings.set_setting(
|
||||||
|
"input/" + ACTION_OPEN_DOC,
|
||||||
|
{
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": [open_current_file_documentation],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
# NB: Initial values DON'T work, see [url]https://github.com/godotengine/godot/issues/56598[/url]
|
||||||
|
#ProjectSettings.set_initial_value(&"input/bbcode_edit/editor/open_current_file_documentation", open_current_file_documentation.duplicate())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func remove_keybinds() -> void:
|
||||||
|
ProjectSettings.set_setting("input/" + BBCodeEdit.ACTION_TOGGLE_BOLD, null)
|
||||||
|
ProjectSettings.set_setting("input/" + BBCodeEdit.ACTION_TOGGLE_ITALIC, null)
|
||||||
|
ProjectSettings.set_setting("input/" + BBCodeEdit.ACTION_TOGGLE_UNDERLINE, null)
|
||||||
|
ProjectSettings.set_setting("input/" + BBCodeEdit.ACTION_TOGGLE_STRIKE, null)
|
||||||
|
|
||||||
|
# This calls ProjectSettings.save(), so please call it last
|
||||||
|
remove_editor_keybinds()
|
||||||
|
|
||||||
|
|
||||||
|
func remove_editor_keybinds() -> void:
|
||||||
|
ProjectSettings.set_setting("input/" + ACTION_OPEN_DOC, null)
|
||||||
|
ProjectSettings.save()
|
||||||
|
|
||||||
|
|
||||||
|
func check_current() -> void:
|
||||||
|
var current_editor := EditorInterface.get_script_editor().get_current_editor()
|
||||||
|
if current_editor == null:
|
||||||
|
return
|
||||||
|
check_bbcode_pretendant(current_editor.get_base_editor())
|
||||||
|
|
||||||
|
|
||||||
|
func check_bbcode_pretendant(pretendant: Control) -> void:
|
||||||
|
if pretendant is CodeEdit and not pretendant.has_meta(&"BBCode_utilities"):
|
||||||
|
add_bbcode_handling(pretendant)
|
||||||
|
|
||||||
|
|
||||||
|
func add_bbcode_handling(code_edit: CodeEdit) -> void:
|
||||||
|
# TODO MAYBE implement automatic script inheritence if script is already overriden by another addon
|
||||||
|
code_edit.set_meta(&"never_changed", true)
|
||||||
|
code_edit.set_script(BBCodeEdit)
|
||||||
|
|
||||||
|
|
||||||
|
## [b]WARING:[/b] not fully implemented for non-current script
|
||||||
|
func open_doc(script: Script, code_edit: CodeEdit = null) -> void:
|
||||||
|
var class_name_: String = script.get_global_name()
|
||||||
|
|
||||||
|
if class_name_ == "":
|
||||||
|
class_name_ = '"' + script.resource_path.trim_prefix("res://") + '"'
|
||||||
|
var bbcode_edit_saved_once: PackedStringArray = EditorInterface.get_meta(&"bbcode_edit_saved_once", PackedStringArray())
|
||||||
|
if code_edit and class_name_ not in bbcode_edit_saved_once:
|
||||||
|
bbcode_edit_saved_once.append(class_name_)
|
||||||
|
print_rich("[color=orange]The script never changed since startup: brute-forcing documentation generation. (See [url=https://github.com/godotengine/godot/pull/95821]godot#95821[/url])[/color]")
|
||||||
|
code_edit.text = code_edit.text
|
||||||
|
EditorInterface.save_all_scenes()
|
||||||
|
elif Scraper.is_current_script_unsaved():
|
||||||
|
# TODO ↑ Fix this for non-current script
|
||||||
|
print_rich("[color=orange]Saving to make godot generate documentation.[/color]")
|
||||||
|
EditorInterface.save_all_scenes()
|
||||||
|
|
||||||
|
elif Scraper.is_current_script_unsaved():
|
||||||
|
print_rich("[color=orange]Saving to make godot generate documentation.[/color]")
|
||||||
|
EditorInterface.save_all_scenes()
|
||||||
|
|
||||||
|
EditorInterface.get_script_editor().get_current_editor().go_to_help.emit.call_deferred("class_name:"+class_name_)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func _unhandled_input(event: InputEvent) -> void:
|
||||||
|
if (
|
||||||
|
InputMap.has_action(ACTION_OPEN_DOC)
|
||||||
|
and InputMap.event_is_action(event, ACTION_OPEN_DOC, true)
|
||||||
|
):
|
||||||
|
# TODO find a workaround for the appearance delay of (*) to check unsaved status.
|
||||||
|
var current_editor := EditorInterface.get_script_editor().get_current_editor()
|
||||||
|
if current_editor == null:
|
||||||
|
return
|
||||||
|
|
||||||
|
var code_edit := current_editor.get_base_editor()
|
||||||
|
if code_edit is CodeEdit:
|
||||||
|
open_doc(EditorInterface.get_script_editor().get_current_script(), code_edit)
|
||||||
1
source/addons/bbcode_edit.editor/bbcode_edit_main.gd.uid
Normal file
1
source/addons/bbcode_edit.editor/bbcode_edit_main.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://cvo3g4cvmjypn
|
||||||
14
source/addons/bbcode_edit.editor/color_picker.tscn
Normal file
14
source/addons/bbcode_edit.editor/color_picker.tscn
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
[gd_scene format=3 uid="uid://ofreh5nfb6pa"]
|
||||||
|
|
||||||
|
[node name="_BBCodeEditColorPicker" type="PopupPanel"]
|
||||||
|
size = Vector2i(306, 584)
|
||||||
|
visible = true
|
||||||
|
|
||||||
|
[node name="ColorPicker" type="ColorPicker" parent="."]
|
||||||
|
offset_left = 4.0
|
||||||
|
offset_top = 4.0
|
||||||
|
offset_right = 302.0
|
||||||
|
offset_bottom = 580.0
|
||||||
|
color = Color(0.83233, 0, 0.367475, 1)
|
||||||
|
deferred_mode = true
|
||||||
|
picker_shape = 3
|
||||||
@ -0,0 +1,937 @@
|
|||||||
|
AESContext
|
||||||
|
AStar2D
|
||||||
|
AStar3D
|
||||||
|
AStarGrid2D
|
||||||
|
AcceptDialog
|
||||||
|
AnimatableBody2D
|
||||||
|
AnimatableBody3D
|
||||||
|
AnimatedSprite2D
|
||||||
|
AnimatedSprite3D
|
||||||
|
AnimatedTexture
|
||||||
|
Animation
|
||||||
|
AnimationLibrary
|
||||||
|
AnimationMixer
|
||||||
|
AnimationNode
|
||||||
|
AnimationNodeAdd2
|
||||||
|
AnimationNodeAdd3
|
||||||
|
AnimationNodeAnimation
|
||||||
|
AnimationNodeBlend2
|
||||||
|
AnimationNodeBlend3
|
||||||
|
AnimationNodeBlendSpace1D
|
||||||
|
AnimationNodeBlendSpace2D
|
||||||
|
AnimationNodeBlendTree
|
||||||
|
AnimationNodeOneShot
|
||||||
|
AnimationNodeOutput
|
||||||
|
AnimationNodeStateMachine
|
||||||
|
AnimationNodeStateMachinePlayback
|
||||||
|
AnimationNodeStateMachineTransition
|
||||||
|
AnimationNodeSub2
|
||||||
|
AnimationNodeSync
|
||||||
|
AnimationNodeTimeScale
|
||||||
|
AnimationNodeTimeSeek
|
||||||
|
AnimationNodeTransition
|
||||||
|
AnimationPlayer
|
||||||
|
AnimationRootNode
|
||||||
|
AnimationTree
|
||||||
|
Area2D
|
||||||
|
Area3D
|
||||||
|
ArrayMesh
|
||||||
|
ArrayOccluder3D
|
||||||
|
AspectRatioContainer
|
||||||
|
AtlasTexture
|
||||||
|
AudioBusLayout
|
||||||
|
AudioEffect
|
||||||
|
AudioEffectAmplify
|
||||||
|
AudioEffectBandLimitFilter
|
||||||
|
AudioEffectBandPassFilter
|
||||||
|
AudioEffectCapture
|
||||||
|
AudioEffectChorus
|
||||||
|
AudioEffectCompressor
|
||||||
|
AudioEffectDelay
|
||||||
|
AudioEffectDistortion
|
||||||
|
AudioEffectEQ
|
||||||
|
AudioEffectEQ10
|
||||||
|
AudioEffectEQ21
|
||||||
|
AudioEffectEQ6
|
||||||
|
AudioEffectFilter
|
||||||
|
AudioEffectHardLimiter
|
||||||
|
AudioEffectHighPassFilter
|
||||||
|
AudioEffectHighShelfFilter
|
||||||
|
AudioEffectInstance
|
||||||
|
AudioEffectLimiter
|
||||||
|
AudioEffectLowPassFilter
|
||||||
|
AudioEffectLowShelfFilter
|
||||||
|
AudioEffectNotchFilter
|
||||||
|
AudioEffectPanner
|
||||||
|
AudioEffectPhaser
|
||||||
|
AudioEffectPitchShift
|
||||||
|
AudioEffectRecord
|
||||||
|
AudioEffectReverb
|
||||||
|
AudioEffectSpectrumAnalyzer
|
||||||
|
AudioEffectSpectrumAnalyzerInstance
|
||||||
|
AudioEffectStereoEnhance
|
||||||
|
AudioListener2D
|
||||||
|
AudioListener3D
|
||||||
|
AudioSample
|
||||||
|
AudioSamplePlayback
|
||||||
|
AudioServer
|
||||||
|
AudioStream
|
||||||
|
AudioStreamGenerator
|
||||||
|
AudioStreamGeneratorPlayback
|
||||||
|
AudioStreamInteractive
|
||||||
|
AudioStreamMP3
|
||||||
|
AudioStreamMicrophone
|
||||||
|
AudioStreamOggVorbis
|
||||||
|
AudioStreamPlayback
|
||||||
|
AudioStreamPlaybackInteractive
|
||||||
|
AudioStreamPlaybackOggVorbis
|
||||||
|
AudioStreamPlaybackPlaylist
|
||||||
|
AudioStreamPlaybackPolyphonic
|
||||||
|
AudioStreamPlaybackResampled
|
||||||
|
AudioStreamPlaybackSynchronized
|
||||||
|
AudioStreamPlayer
|
||||||
|
AudioStreamPlayer2D
|
||||||
|
AudioStreamPlayer3D
|
||||||
|
AudioStreamPlaylist
|
||||||
|
AudioStreamPolyphonic
|
||||||
|
AudioStreamRandomizer
|
||||||
|
AudioStreamSynchronized
|
||||||
|
AudioStreamWAV
|
||||||
|
BackBufferCopy
|
||||||
|
BaseButton
|
||||||
|
BaseMaterial3D
|
||||||
|
BitMap
|
||||||
|
Bone2D
|
||||||
|
BoneAttachment3D
|
||||||
|
BoneMap
|
||||||
|
BoxContainer
|
||||||
|
BoxMesh
|
||||||
|
BoxOccluder3D
|
||||||
|
BoxShape3D
|
||||||
|
Button
|
||||||
|
ButtonGroup
|
||||||
|
CPUParticles2D
|
||||||
|
CPUParticles3D
|
||||||
|
CSGBox3D
|
||||||
|
CSGCombiner3D
|
||||||
|
CSGCylinder3D
|
||||||
|
CSGMesh3D
|
||||||
|
CSGPolygon3D
|
||||||
|
CSGPrimitive3D
|
||||||
|
CSGShape3D
|
||||||
|
CSGSphere3D
|
||||||
|
CSGTorus3D
|
||||||
|
CallbackTweener
|
||||||
|
Camera2D
|
||||||
|
Camera3D
|
||||||
|
CameraAttributes
|
||||||
|
CameraAttributesPhysical
|
||||||
|
CameraAttributesPractical
|
||||||
|
CameraFeed
|
||||||
|
CameraServer
|
||||||
|
CameraTexture
|
||||||
|
CanvasGroup
|
||||||
|
CanvasItem
|
||||||
|
CanvasItemMaterial
|
||||||
|
CanvasLayer
|
||||||
|
CanvasModulate
|
||||||
|
CanvasTexture
|
||||||
|
CapsuleMesh
|
||||||
|
CapsuleShape2D
|
||||||
|
CapsuleShape3D
|
||||||
|
CenterContainer
|
||||||
|
CharFXTransform
|
||||||
|
CharacterBody2D
|
||||||
|
CharacterBody3D
|
||||||
|
CheckBox
|
||||||
|
CheckButton
|
||||||
|
CircleShape2D
|
||||||
|
ClassDB
|
||||||
|
CodeEdit
|
||||||
|
CodeHighlighter
|
||||||
|
CollisionObject2D
|
||||||
|
CollisionObject3D
|
||||||
|
CollisionPolygon2D
|
||||||
|
CollisionPolygon3D
|
||||||
|
CollisionShape2D
|
||||||
|
CollisionShape3D
|
||||||
|
ColorPicker
|
||||||
|
ColorPickerButton
|
||||||
|
ColorRect
|
||||||
|
Compositor
|
||||||
|
CompositorEffect
|
||||||
|
CompressedCubemap
|
||||||
|
CompressedCubemapArray
|
||||||
|
CompressedTexture2D
|
||||||
|
CompressedTexture2DArray
|
||||||
|
CompressedTexture3D
|
||||||
|
CompressedTextureLayered
|
||||||
|
ConcavePolygonShape2D
|
||||||
|
ConcavePolygonShape3D
|
||||||
|
ConeTwistJoint3D
|
||||||
|
ConfigFile
|
||||||
|
ConfirmationDialog
|
||||||
|
Container
|
||||||
|
Control
|
||||||
|
ConvexPolygonShape2D
|
||||||
|
ConvexPolygonShape3D
|
||||||
|
Crypto
|
||||||
|
CryptoKey
|
||||||
|
Cubemap
|
||||||
|
CubemapArray
|
||||||
|
Curve
|
||||||
|
Curve2D
|
||||||
|
Curve3D
|
||||||
|
CurveTexture
|
||||||
|
CurveXYZTexture
|
||||||
|
CylinderMesh
|
||||||
|
CylinderShape3D
|
||||||
|
DTLSServer
|
||||||
|
DampedSpringJoint2D
|
||||||
|
Decal
|
||||||
|
DirAccess
|
||||||
|
DirectionalLight2D
|
||||||
|
DirectionalLight3D
|
||||||
|
DisplayServer
|
||||||
|
ENetConnection
|
||||||
|
ENetMultiplayerPeer
|
||||||
|
ENetPacketPeer
|
||||||
|
EditorCommandPalette
|
||||||
|
EditorDebuggerPlugin
|
||||||
|
EditorDebuggerSession
|
||||||
|
EditorExportPlatform
|
||||||
|
EditorExportPlatformAndroid
|
||||||
|
EditorExportPlatformIOS
|
||||||
|
EditorExportPlatformLinuxBSD
|
||||||
|
EditorExportPlatformMacOS
|
||||||
|
EditorExportPlatformPC
|
||||||
|
EditorExportPlatformWeb
|
||||||
|
EditorExportPlatformWindows
|
||||||
|
EditorExportPlugin
|
||||||
|
EditorFeatureProfile
|
||||||
|
EditorFileDialog
|
||||||
|
EditorFileSystem
|
||||||
|
EditorFileSystemDirectory
|
||||||
|
EditorFileSystemImportFormatSupportQuery
|
||||||
|
EditorImportPlugin
|
||||||
|
EditorInspector
|
||||||
|
EditorInspectorPlugin
|
||||||
|
EditorInterface
|
||||||
|
EditorNode3DGizmo
|
||||||
|
EditorNode3DGizmoPlugin
|
||||||
|
EditorPaths
|
||||||
|
EditorPlugin
|
||||||
|
EditorProperty
|
||||||
|
EditorResourceConversionPlugin
|
||||||
|
EditorResourcePicker
|
||||||
|
EditorResourcePreview
|
||||||
|
EditorResourcePreviewGenerator
|
||||||
|
EditorResourceTooltipPlugin
|
||||||
|
EditorSceneFormatImporter
|
||||||
|
EditorSceneFormatImporterBlend
|
||||||
|
EditorSceneFormatImporterFBX2GLTF
|
||||||
|
EditorSceneFormatImporterGLTF
|
||||||
|
EditorSceneFormatImporterUFBX
|
||||||
|
EditorScenePostImport
|
||||||
|
EditorScenePostImportPlugin
|
||||||
|
EditorScript
|
||||||
|
EditorScriptPicker
|
||||||
|
EditorSelection
|
||||||
|
EditorSettings
|
||||||
|
EditorSpinSlider
|
||||||
|
EditorSyntaxHighlighter
|
||||||
|
EditorTranslationParserPlugin
|
||||||
|
EditorUndoRedoManager
|
||||||
|
EditorVCSInterface
|
||||||
|
EncodedObjectAsID
|
||||||
|
Engine
|
||||||
|
EngineDebugger
|
||||||
|
EngineProfiler
|
||||||
|
Environment
|
||||||
|
Expression
|
||||||
|
FBXDocument
|
||||||
|
FBXState
|
||||||
|
FastNoiseLite
|
||||||
|
FileAccess
|
||||||
|
FileDialog
|
||||||
|
FileSystemDock
|
||||||
|
FlowContainer
|
||||||
|
FogMaterial
|
||||||
|
FogVolume
|
||||||
|
Font
|
||||||
|
FontFile
|
||||||
|
FontVariation
|
||||||
|
FramebufferCacheRD
|
||||||
|
GDExtension
|
||||||
|
GDExtensionManager
|
||||||
|
GDScript
|
||||||
|
GDScriptEditorTranslationParserPlugin
|
||||||
|
GDScriptNativeClass
|
||||||
|
GLTFAccessor
|
||||||
|
GLTFAnimation
|
||||||
|
GLTFBufferView
|
||||||
|
GLTFCamera
|
||||||
|
GLTFDocument
|
||||||
|
GLTFDocumentExtension
|
||||||
|
GLTFDocumentExtensionConvertImporterMesh
|
||||||
|
GLTFDocumentExtensionPhysics
|
||||||
|
GLTFDocumentExtensionTextureKTX
|
||||||
|
GLTFDocumentExtensionTextureWebP
|
||||||
|
GLTFLight
|
||||||
|
GLTFMesh
|
||||||
|
GLTFNode
|
||||||
|
GLTFPhysicsBody
|
||||||
|
GLTFPhysicsShape
|
||||||
|
GLTFSkeleton
|
||||||
|
GLTFSkin
|
||||||
|
GLTFSpecGloss
|
||||||
|
GLTFState
|
||||||
|
GLTFTexture
|
||||||
|
GLTFTextureSampler
|
||||||
|
GPUParticles2D
|
||||||
|
GPUParticles3D
|
||||||
|
GPUParticlesAttractor3D
|
||||||
|
GPUParticlesAttractorBox3D
|
||||||
|
GPUParticlesAttractorSphere3D
|
||||||
|
GPUParticlesAttractorVectorField3D
|
||||||
|
GPUParticlesCollision3D
|
||||||
|
GPUParticlesCollisionBox3D
|
||||||
|
GPUParticlesCollisionHeightField3D
|
||||||
|
GPUParticlesCollisionSDF3D
|
||||||
|
GPUParticlesCollisionSphere3D
|
||||||
|
Generic6DOFJoint3D
|
||||||
|
Geometry2D
|
||||||
|
Geometry3D
|
||||||
|
GeometryInstance3D
|
||||||
|
GodotNavigationServer2D
|
||||||
|
GodotPhysicsServer2D
|
||||||
|
GodotPhysicsServer3D
|
||||||
|
Gradient
|
||||||
|
GradientTexture1D
|
||||||
|
GradientTexture2D
|
||||||
|
GraphEdit
|
||||||
|
GraphElement
|
||||||
|
GraphFrame
|
||||||
|
GraphNode
|
||||||
|
GridContainer
|
||||||
|
GridMap
|
||||||
|
GrooveJoint2D
|
||||||
|
HBoxContainer
|
||||||
|
HFlowContainer
|
||||||
|
HMACContext
|
||||||
|
HScrollBar
|
||||||
|
HSeparator
|
||||||
|
HSlider
|
||||||
|
HSplitContainer
|
||||||
|
HTTPClient
|
||||||
|
HTTPRequest
|
||||||
|
HashingContext
|
||||||
|
HeightMapShape3D
|
||||||
|
HingeJoint3D
|
||||||
|
IP
|
||||||
|
IPUnix
|
||||||
|
Image
|
||||||
|
ImageFormatLoader
|
||||||
|
ImageFormatLoaderExtension
|
||||||
|
ImageTexture
|
||||||
|
ImageTexture3D
|
||||||
|
ImageTextureLayered
|
||||||
|
ImmediateMesh
|
||||||
|
ImporterMesh
|
||||||
|
ImporterMeshInstance3D
|
||||||
|
Input
|
||||||
|
InputEvent
|
||||||
|
InputEventAction
|
||||||
|
InputEventFromWindow
|
||||||
|
InputEventGesture
|
||||||
|
InputEventJoypadButton
|
||||||
|
InputEventJoypadMotion
|
||||||
|
InputEventKey
|
||||||
|
InputEventMIDI
|
||||||
|
InputEventMagnifyGesture
|
||||||
|
InputEventMouse
|
||||||
|
InputEventMouseButton
|
||||||
|
InputEventMouseMotion
|
||||||
|
InputEventPanGesture
|
||||||
|
InputEventScreenDrag
|
||||||
|
InputEventScreenTouch
|
||||||
|
InputEventShortcut
|
||||||
|
InputEventWithModifiers
|
||||||
|
InputMap
|
||||||
|
InstancePlaceholder
|
||||||
|
IntervalTweener
|
||||||
|
ItemList
|
||||||
|
JNISingleton
|
||||||
|
JSON
|
||||||
|
JSONRPC
|
||||||
|
JavaClass
|
||||||
|
JavaClassWrapper
|
||||||
|
JavaScriptBridge
|
||||||
|
JavaScriptObject
|
||||||
|
Joint2D
|
||||||
|
Joint3D
|
||||||
|
KinematicCollision2D
|
||||||
|
KinematicCollision3D
|
||||||
|
Label
|
||||||
|
Label3D
|
||||||
|
LabelSettings
|
||||||
|
Light2D
|
||||||
|
Light3D
|
||||||
|
LightOccluder2D
|
||||||
|
LightmapGI
|
||||||
|
LightmapGIData
|
||||||
|
LightmapProbe
|
||||||
|
Lightmapper
|
||||||
|
LightmapperRD
|
||||||
|
Line2D
|
||||||
|
LineEdit
|
||||||
|
LinkButton
|
||||||
|
MainLoop
|
||||||
|
MarginContainer
|
||||||
|
Marker2D
|
||||||
|
Marker3D
|
||||||
|
Marshalls
|
||||||
|
Material
|
||||||
|
MenuBar
|
||||||
|
MenuButton
|
||||||
|
Mesh
|
||||||
|
MeshConvexDecompositionSettings
|
||||||
|
MeshDataTool
|
||||||
|
MeshInstance2D
|
||||||
|
MeshInstance3D
|
||||||
|
MeshLibrary
|
||||||
|
MeshTexture
|
||||||
|
MethodTweener
|
||||||
|
MissingNode
|
||||||
|
MissingResource
|
||||||
|
MobileVRInterface
|
||||||
|
MovieWriter
|
||||||
|
MovieWriterMJPEG
|
||||||
|
MovieWriterPNGWAV
|
||||||
|
MultiMesh
|
||||||
|
MultiMeshInstance2D
|
||||||
|
MultiMeshInstance3D
|
||||||
|
MultiplayerAPI
|
||||||
|
MultiplayerAPIExtension
|
||||||
|
MultiplayerPeer
|
||||||
|
MultiplayerPeerExtension
|
||||||
|
MultiplayerSpawner
|
||||||
|
MultiplayerSynchronizer
|
||||||
|
Mutex
|
||||||
|
NativeMenu
|
||||||
|
NativeMenuWindows
|
||||||
|
NavigationAgent2D
|
||||||
|
NavigationAgent3D
|
||||||
|
NavigationLink2D
|
||||||
|
NavigationLink3D
|
||||||
|
NavigationMesh
|
||||||
|
NavigationMeshGenerator
|
||||||
|
NavigationMeshSourceGeometryData2D
|
||||||
|
NavigationMeshSourceGeometryData3D
|
||||||
|
NavigationObstacle2D
|
||||||
|
NavigationObstacle3D
|
||||||
|
NavigationPathQueryParameters2D
|
||||||
|
NavigationPathQueryParameters3D
|
||||||
|
NavigationPathQueryResult2D
|
||||||
|
NavigationPathQueryResult3D
|
||||||
|
NavigationPolygon
|
||||||
|
NavigationRegion2D
|
||||||
|
NavigationRegion3D
|
||||||
|
NavigationServer2D
|
||||||
|
NavigationServer3D
|
||||||
|
NinePatchRect
|
||||||
|
Node
|
||||||
|
Node2D
|
||||||
|
Node3D
|
||||||
|
Node3DGizmo
|
||||||
|
Noise
|
||||||
|
NoiseTexture2D
|
||||||
|
NoiseTexture3D
|
||||||
|
ORMMaterial3D
|
||||||
|
OS
|
||||||
|
Object
|
||||||
|
Occluder3D
|
||||||
|
OccluderInstance3D
|
||||||
|
OccluderPolygon2D
|
||||||
|
OfflineMultiplayerPeer
|
||||||
|
OggPacketSequence
|
||||||
|
OggPacketSequencePlayback
|
||||||
|
OmniLight3D
|
||||||
|
OpenXRAPIExtension
|
||||||
|
OpenXRAction
|
||||||
|
OpenXRActionMap
|
||||||
|
OpenXRActionSet
|
||||||
|
OpenXRCompositionLayer
|
||||||
|
OpenXRCompositionLayerCylinder
|
||||||
|
OpenXRCompositionLayerEquirect
|
||||||
|
OpenXRCompositionLayerQuad
|
||||||
|
OpenXRExtensionWrapperExtension
|
||||||
|
OpenXRHand
|
||||||
|
OpenXRIPBinding
|
||||||
|
OpenXRInteractionProfile
|
||||||
|
OpenXRInteractionProfileMetadata
|
||||||
|
OpenXRInterface
|
||||||
|
OptimizedTranslation
|
||||||
|
OptionButton
|
||||||
|
PCKPacker
|
||||||
|
PackedDataContainer
|
||||||
|
PackedDataContainerRef
|
||||||
|
PackedScene
|
||||||
|
PacketPeer
|
||||||
|
PacketPeerDTLS
|
||||||
|
PacketPeerExtension
|
||||||
|
PacketPeerStream
|
||||||
|
PacketPeerUDP
|
||||||
|
Panel
|
||||||
|
PanelContainer
|
||||||
|
PanoramaSkyMaterial
|
||||||
|
Parallax2D
|
||||||
|
ParallaxBackground
|
||||||
|
ParallaxLayer
|
||||||
|
ParticleProcessMaterial
|
||||||
|
Path2D
|
||||||
|
Path3D
|
||||||
|
PathFollow2D
|
||||||
|
PathFollow3D
|
||||||
|
Performance
|
||||||
|
PhysicalBone2D
|
||||||
|
PhysicalBone3D
|
||||||
|
PhysicalBoneSimulator3D
|
||||||
|
PhysicalSkyMaterial
|
||||||
|
PhysicsBody2D
|
||||||
|
PhysicsBody3D
|
||||||
|
PhysicsDirectBodyState2D
|
||||||
|
PhysicsDirectBodyState2DExtension
|
||||||
|
PhysicsDirectBodyState3D
|
||||||
|
PhysicsDirectBodyState3DExtension
|
||||||
|
PhysicsDirectSpaceState2D
|
||||||
|
PhysicsDirectSpaceState2DExtension
|
||||||
|
PhysicsDirectSpaceState3D
|
||||||
|
PhysicsDirectSpaceState3DExtension
|
||||||
|
PhysicsMaterial
|
||||||
|
PhysicsPointQueryParameters2D
|
||||||
|
PhysicsPointQueryParameters3D
|
||||||
|
PhysicsRayQueryParameters2D
|
||||||
|
PhysicsRayQueryParameters3D
|
||||||
|
PhysicsServer2D
|
||||||
|
PhysicsServer2DExtension
|
||||||
|
PhysicsServer2DManager
|
||||||
|
PhysicsServer3D
|
||||||
|
PhysicsServer3DExtension
|
||||||
|
PhysicsServer3DManager
|
||||||
|
PhysicsServer3DRenderingServerHandler
|
||||||
|
PhysicsShapeQueryParameters2D
|
||||||
|
PhysicsShapeQueryParameters3D
|
||||||
|
PhysicsTestMotionParameters2D
|
||||||
|
PhysicsTestMotionParameters3D
|
||||||
|
PhysicsTestMotionResult2D
|
||||||
|
PhysicsTestMotionResult3D
|
||||||
|
PinJoint2D
|
||||||
|
PinJoint3D
|
||||||
|
PlaceholderCubemap
|
||||||
|
PlaceholderCubemapArray
|
||||||
|
PlaceholderMaterial
|
||||||
|
PlaceholderMesh
|
||||||
|
PlaceholderTexture2D
|
||||||
|
PlaceholderTexture2DArray
|
||||||
|
PlaceholderTexture3D
|
||||||
|
PlaceholderTextureLayered
|
||||||
|
PlaneMesh
|
||||||
|
PointLight2D
|
||||||
|
PointMesh
|
||||||
|
Polygon2D
|
||||||
|
PolygonOccluder3D
|
||||||
|
PolygonPathFinder
|
||||||
|
Popup
|
||||||
|
PopupMenu
|
||||||
|
PopupPanel
|
||||||
|
PortableCompressedTexture2D
|
||||||
|
PrimitiveMesh
|
||||||
|
PrismMesh
|
||||||
|
ProceduralSkyMaterial
|
||||||
|
ProgressBar
|
||||||
|
ProjectSettings
|
||||||
|
PropertyTweener
|
||||||
|
QuadMesh
|
||||||
|
QuadOccluder3D
|
||||||
|
RDAttachmentFormat
|
||||||
|
RDFramebufferPass
|
||||||
|
RDPipelineColorBlendState
|
||||||
|
RDPipelineColorBlendStateAttachment
|
||||||
|
RDPipelineDepthStencilState
|
||||||
|
RDPipelineMultisampleState
|
||||||
|
RDPipelineRasterizationState
|
||||||
|
RDPipelineSpecializationConstant
|
||||||
|
RDSamplerState
|
||||||
|
RDShaderFile
|
||||||
|
RDShaderSPIRV
|
||||||
|
RDShaderSource
|
||||||
|
RDTextureFormat
|
||||||
|
RDTextureView
|
||||||
|
RDUniform
|
||||||
|
RDVertexAttribute
|
||||||
|
RandomNumberGenerator
|
||||||
|
Range
|
||||||
|
RayCast2D
|
||||||
|
RayCast3D
|
||||||
|
RectangleShape2D
|
||||||
|
RefCounted
|
||||||
|
ReferenceRect
|
||||||
|
ReflectionProbe
|
||||||
|
RegEx
|
||||||
|
RegExMatch
|
||||||
|
RemoteTransform2D
|
||||||
|
RemoteTransform3D
|
||||||
|
RenderData
|
||||||
|
RenderDataExtension
|
||||||
|
RenderDataRD
|
||||||
|
RenderSceneBuffers
|
||||||
|
RenderSceneBuffersConfiguration
|
||||||
|
RenderSceneBuffersExtension
|
||||||
|
RenderSceneBuffersRD
|
||||||
|
RenderSceneData
|
||||||
|
RenderSceneDataExtension
|
||||||
|
RenderSceneDataRD
|
||||||
|
RenderingDevice
|
||||||
|
RenderingServer
|
||||||
|
Resource
|
||||||
|
ResourceFormatImporterSaver
|
||||||
|
ResourceFormatLoader
|
||||||
|
ResourceFormatSaver
|
||||||
|
ResourceImporter
|
||||||
|
ResourceImporterBMFont
|
||||||
|
ResourceImporterBitMap
|
||||||
|
ResourceImporterCSVTranslation
|
||||||
|
ResourceImporterDynamicFont
|
||||||
|
ResourceImporterImage
|
||||||
|
ResourceImporterImageFont
|
||||||
|
ResourceImporterLayeredTexture
|
||||||
|
ResourceImporterMP3
|
||||||
|
ResourceImporterOBJ
|
||||||
|
ResourceImporterOggVorbis
|
||||||
|
ResourceImporterScene
|
||||||
|
ResourceImporterShaderFile
|
||||||
|
ResourceImporterTexture
|
||||||
|
ResourceImporterTextureAtlas
|
||||||
|
ResourceImporterWAV
|
||||||
|
ResourceLoader
|
||||||
|
ResourcePreloader
|
||||||
|
ResourceSaver
|
||||||
|
ResourceUID
|
||||||
|
RibbonTrailMesh
|
||||||
|
RichTextEffect
|
||||||
|
RichTextLabel
|
||||||
|
RigidBody2D
|
||||||
|
RigidBody3D
|
||||||
|
RootMotionView
|
||||||
|
SceneCacheInterface
|
||||||
|
SceneMultiplayer
|
||||||
|
SceneRPCInterface
|
||||||
|
SceneReplicationConfig
|
||||||
|
SceneReplicationInterface
|
||||||
|
SceneState
|
||||||
|
SceneTree
|
||||||
|
SceneTreeTimer
|
||||||
|
Script
|
||||||
|
ScriptCreateDialog
|
||||||
|
ScriptEditor
|
||||||
|
ScriptEditorBase
|
||||||
|
ScriptExtension
|
||||||
|
ScriptLanguage
|
||||||
|
ScriptLanguageExtension
|
||||||
|
ScrollBar
|
||||||
|
ScrollContainer
|
||||||
|
SegmentShape2D
|
||||||
|
Semaphore
|
||||||
|
SeparationRayShape2D
|
||||||
|
SeparationRayShape3D
|
||||||
|
Separator
|
||||||
|
Shader
|
||||||
|
ShaderGlobalsOverride
|
||||||
|
ShaderInclude
|
||||||
|
ShaderMaterial
|
||||||
|
Shape2D
|
||||||
|
Shape3D
|
||||||
|
ShapeCast2D
|
||||||
|
ShapeCast3D
|
||||||
|
Shortcut
|
||||||
|
Skeleton2D
|
||||||
|
Skeleton3D
|
||||||
|
SkeletonIK3D
|
||||||
|
SkeletonModification2D
|
||||||
|
SkeletonModification2DCCDIK
|
||||||
|
SkeletonModification2DFABRIK
|
||||||
|
SkeletonModification2DJiggle
|
||||||
|
SkeletonModification2DLookAt
|
||||||
|
SkeletonModification2DPhysicalBones
|
||||||
|
SkeletonModification2DStackHolder
|
||||||
|
SkeletonModification2DTwoBoneIK
|
||||||
|
SkeletonModificationStack2D
|
||||||
|
SkeletonModifier3D
|
||||||
|
SkeletonProfile
|
||||||
|
SkeletonProfileHumanoid
|
||||||
|
Skin
|
||||||
|
SkinReference
|
||||||
|
Sky
|
||||||
|
Slider
|
||||||
|
SliderJoint3D
|
||||||
|
SoftBody3D
|
||||||
|
SphereMesh
|
||||||
|
SphereOccluder3D
|
||||||
|
SphereShape3D
|
||||||
|
SpinBox
|
||||||
|
SplitContainer
|
||||||
|
SpotLight3D
|
||||||
|
SpringArm3D
|
||||||
|
Sprite2D
|
||||||
|
Sprite3D
|
||||||
|
SpriteBase3D
|
||||||
|
SpriteFrames
|
||||||
|
StandardMaterial3D
|
||||||
|
StaticBody2D
|
||||||
|
StaticBody3D
|
||||||
|
StatusIndicator
|
||||||
|
StreamPeer
|
||||||
|
StreamPeerBuffer
|
||||||
|
StreamPeerExtension
|
||||||
|
StreamPeerGZIP
|
||||||
|
StreamPeerTCP
|
||||||
|
StreamPeerTLS
|
||||||
|
StyleBox
|
||||||
|
StyleBoxEmpty
|
||||||
|
StyleBoxFlat
|
||||||
|
StyleBoxLine
|
||||||
|
StyleBoxTexture
|
||||||
|
SubViewport
|
||||||
|
SubViewportContainer
|
||||||
|
SurfaceTool
|
||||||
|
SyntaxHighlighter
|
||||||
|
SystemFont
|
||||||
|
TCPServer
|
||||||
|
TLSOptions
|
||||||
|
TabBar
|
||||||
|
TabContainer
|
||||||
|
TextEdit
|
||||||
|
TextLine
|
||||||
|
TextMesh
|
||||||
|
TextParagraph
|
||||||
|
TextServer
|
||||||
|
TextServerAdvanced
|
||||||
|
TextServerDummy
|
||||||
|
TextServerExtension
|
||||||
|
TextServerManager
|
||||||
|
Texture
|
||||||
|
Texture2D
|
||||||
|
Texture2DArray
|
||||||
|
Texture2DArrayRD
|
||||||
|
Texture2DRD
|
||||||
|
Texture3D
|
||||||
|
Texture3DRD
|
||||||
|
TextureButton
|
||||||
|
TextureCubemapArrayRD
|
||||||
|
TextureCubemapRD
|
||||||
|
TextureLayered
|
||||||
|
TextureLayeredRD
|
||||||
|
TextureProgressBar
|
||||||
|
TextureRect
|
||||||
|
Theme
|
||||||
|
ThemeContext
|
||||||
|
ThemeDB
|
||||||
|
Thread
|
||||||
|
TileData
|
||||||
|
TileMap
|
||||||
|
TileMapLayer
|
||||||
|
TileMapPattern
|
||||||
|
TileSet
|
||||||
|
TileSetAtlasSource
|
||||||
|
TileSetScenesCollectionSource
|
||||||
|
TileSetSource
|
||||||
|
Time
|
||||||
|
Timer
|
||||||
|
TorusMesh
|
||||||
|
TouchScreenButton
|
||||||
|
Translation
|
||||||
|
TranslationServer
|
||||||
|
Tree
|
||||||
|
TreeItem
|
||||||
|
TriangleMesh
|
||||||
|
TubeTrailMesh
|
||||||
|
Tween
|
||||||
|
Tweener
|
||||||
|
UDPServer
|
||||||
|
UPNP
|
||||||
|
UPNPDevice
|
||||||
|
UndoRedo
|
||||||
|
UniformSetCacheRD
|
||||||
|
VBoxContainer
|
||||||
|
VFlowContainer
|
||||||
|
VScrollBar
|
||||||
|
VSeparator
|
||||||
|
VSlider
|
||||||
|
VSplitContainer
|
||||||
|
VehicleBody3D
|
||||||
|
VehicleWheel3D
|
||||||
|
VideoStream
|
||||||
|
VideoStreamPlayback
|
||||||
|
VideoStreamPlayer
|
||||||
|
VideoStreamTheora
|
||||||
|
Viewport
|
||||||
|
ViewportTexture
|
||||||
|
VisibleOnScreenEnabler2D
|
||||||
|
VisibleOnScreenEnabler3D
|
||||||
|
VisibleOnScreenNotifier2D
|
||||||
|
VisibleOnScreenNotifier3D
|
||||||
|
VisualInstance3D
|
||||||
|
VisualShader
|
||||||
|
VisualShaderNode
|
||||||
|
VisualShaderNodeBillboard
|
||||||
|
VisualShaderNodeBooleanConstant
|
||||||
|
VisualShaderNodeBooleanParameter
|
||||||
|
VisualShaderNodeClamp
|
||||||
|
VisualShaderNodeColorConstant
|
||||||
|
VisualShaderNodeColorFunc
|
||||||
|
VisualShaderNodeColorOp
|
||||||
|
VisualShaderNodeColorParameter
|
||||||
|
VisualShaderNodeComment
|
||||||
|
VisualShaderNodeCompare
|
||||||
|
VisualShaderNodeConstant
|
||||||
|
VisualShaderNodeCubemap
|
||||||
|
VisualShaderNodeCubemapParameter
|
||||||
|
VisualShaderNodeCurveTexture
|
||||||
|
VisualShaderNodeCurveXYZTexture
|
||||||
|
VisualShaderNodeCustom
|
||||||
|
VisualShaderNodeDerivativeFunc
|
||||||
|
VisualShaderNodeDeterminant
|
||||||
|
VisualShaderNodeDistanceFade
|
||||||
|
VisualShaderNodeDotProduct
|
||||||
|
VisualShaderNodeExpression
|
||||||
|
VisualShaderNodeFaceForward
|
||||||
|
VisualShaderNodeFloatConstant
|
||||||
|
VisualShaderNodeFloatFunc
|
||||||
|
VisualShaderNodeFloatOp
|
||||||
|
VisualShaderNodeFloatParameter
|
||||||
|
VisualShaderNodeFrame
|
||||||
|
VisualShaderNodeFresnel
|
||||||
|
VisualShaderNodeGlobalExpression
|
||||||
|
VisualShaderNodeGroupBase
|
||||||
|
VisualShaderNodeIf
|
||||||
|
VisualShaderNodeInput
|
||||||
|
VisualShaderNodeIntConstant
|
||||||
|
VisualShaderNodeIntFunc
|
||||||
|
VisualShaderNodeIntOp
|
||||||
|
VisualShaderNodeIntParameter
|
||||||
|
VisualShaderNodeIs
|
||||||
|
VisualShaderNodeLinearSceneDepth
|
||||||
|
VisualShaderNodeMix
|
||||||
|
VisualShaderNodeMultiplyAdd
|
||||||
|
VisualShaderNodeOuterProduct
|
||||||
|
VisualShaderNodeOutput
|
||||||
|
VisualShaderNodeParameter
|
||||||
|
VisualShaderNodeParameterRef
|
||||||
|
VisualShaderNodeParticleAccelerator
|
||||||
|
VisualShaderNodeParticleBoxEmitter
|
||||||
|
VisualShaderNodeParticleConeVelocity
|
||||||
|
VisualShaderNodeParticleEmit
|
||||||
|
VisualShaderNodeParticleEmitter
|
||||||
|
VisualShaderNodeParticleMeshEmitter
|
||||||
|
VisualShaderNodeParticleMultiplyByAxisAngle
|
||||||
|
VisualShaderNodeParticleOutput
|
||||||
|
VisualShaderNodeParticleRandomness
|
||||||
|
VisualShaderNodeParticleRingEmitter
|
||||||
|
VisualShaderNodeParticleSphereEmitter
|
||||||
|
VisualShaderNodeProximityFade
|
||||||
|
VisualShaderNodeRandomRange
|
||||||
|
VisualShaderNodeRemap
|
||||||
|
VisualShaderNodeReroute
|
||||||
|
VisualShaderNodeResizableBase
|
||||||
|
VisualShaderNodeRotationByAxis
|
||||||
|
VisualShaderNodeSDFRaymarch
|
||||||
|
VisualShaderNodeSDFToScreenUV
|
||||||
|
VisualShaderNodeSample3D
|
||||||
|
VisualShaderNodeScreenNormalWorldSpace
|
||||||
|
VisualShaderNodeScreenUVToSDF
|
||||||
|
VisualShaderNodeSmoothStep
|
||||||
|
VisualShaderNodeStep
|
||||||
|
VisualShaderNodeSwitch
|
||||||
|
VisualShaderNodeTexture
|
||||||
|
VisualShaderNodeTexture2DArray
|
||||||
|
VisualShaderNodeTexture2DArrayParameter
|
||||||
|
VisualShaderNodeTexture2DParameter
|
||||||
|
VisualShaderNodeTexture3D
|
||||||
|
VisualShaderNodeTexture3DParameter
|
||||||
|
VisualShaderNodeTextureParameter
|
||||||
|
VisualShaderNodeTextureParameterTriplanar
|
||||||
|
VisualShaderNodeTextureSDF
|
||||||
|
VisualShaderNodeTextureSDFNormal
|
||||||
|
VisualShaderNodeTransformCompose
|
||||||
|
VisualShaderNodeTransformConstant
|
||||||
|
VisualShaderNodeTransformDecompose
|
||||||
|
VisualShaderNodeTransformFunc
|
||||||
|
VisualShaderNodeTransformOp
|
||||||
|
VisualShaderNodeTransformParameter
|
||||||
|
VisualShaderNodeTransformVecMult
|
||||||
|
VisualShaderNodeUIntConstant
|
||||||
|
VisualShaderNodeUIntFunc
|
||||||
|
VisualShaderNodeUIntOp
|
||||||
|
VisualShaderNodeUIntParameter
|
||||||
|
VisualShaderNodeUVFunc
|
||||||
|
VisualShaderNodeUVPolarCoord
|
||||||
|
VisualShaderNodeVarying
|
||||||
|
VisualShaderNodeVaryingGetter
|
||||||
|
VisualShaderNodeVaryingSetter
|
||||||
|
VisualShaderNodeVec2Constant
|
||||||
|
VisualShaderNodeVec2Parameter
|
||||||
|
VisualShaderNodeVec3Constant
|
||||||
|
VisualShaderNodeVec3Parameter
|
||||||
|
VisualShaderNodeVec4Constant
|
||||||
|
VisualShaderNodeVec4Parameter
|
||||||
|
VisualShaderNodeVectorBase
|
||||||
|
VisualShaderNodeVectorCompose
|
||||||
|
VisualShaderNodeVectorDecompose
|
||||||
|
VisualShaderNodeVectorDistance
|
||||||
|
VisualShaderNodeVectorFunc
|
||||||
|
VisualShaderNodeVectorLen
|
||||||
|
VisualShaderNodeVectorOp
|
||||||
|
VisualShaderNodeVectorRefract
|
||||||
|
VisualShaderNodeWorldPositionFromDepth
|
||||||
|
VoxelGI
|
||||||
|
VoxelGIData
|
||||||
|
WeakRef
|
||||||
|
WebRTCDataChannel
|
||||||
|
WebRTCDataChannelExtension
|
||||||
|
WebRTCMultiplayerPeer
|
||||||
|
WebRTCPeerConnection
|
||||||
|
WebRTCPeerConnectionExtension
|
||||||
|
WebSocketMultiplayerPeer
|
||||||
|
WebSocketPeer
|
||||||
|
WebXRInterface
|
||||||
|
Window
|
||||||
|
WorkerThreadPool
|
||||||
|
World2D
|
||||||
|
World3D
|
||||||
|
WorldBoundaryShape2D
|
||||||
|
WorldBoundaryShape3D
|
||||||
|
WorldEnvironment
|
||||||
|
X509Certificate
|
||||||
|
XMLParser
|
||||||
|
XRAnchor3D
|
||||||
|
XRBodyModifier3D
|
||||||
|
XRBodyTracker
|
||||||
|
XRCamera3D
|
||||||
|
XRController3D
|
||||||
|
XRControllerTracker
|
||||||
|
XRFaceModifier3D
|
||||||
|
XRFaceTracker
|
||||||
|
XRHandModifier3D
|
||||||
|
XRHandTracker
|
||||||
|
XRInterface
|
||||||
|
XRInterfaceExtension
|
||||||
|
XRNode3D
|
||||||
|
XROrigin3D
|
||||||
|
XRPose
|
||||||
|
XRPositionalTracker
|
||||||
|
XRServer
|
||||||
|
XRTracker
|
||||||
|
XRVRS
|
||||||
|
ZIPPacker
|
||||||
|
ZIPReader
|
||||||
265
source/addons/bbcode_edit.editor/completions_db/completions.gd
Normal file
265
source/addons/bbcode_edit.editor/completions_db/completions.gd
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
extends Object
|
||||||
|
|
||||||
|
|
||||||
|
const Scraper = preload("res://addons/bbcode_edit.editor/editor_interface_scraper.gd")
|
||||||
|
|
||||||
|
|
||||||
|
const PATH_BUILTIN_COMPLETIONS = "res://addons/bbcode_edit.editor/completions_db/builtin_classes.txt"
|
||||||
|
|
||||||
|
|
||||||
|
# TODO add all tags and classify them between Documentation Only, Documentation Forbidden, Universal
|
||||||
|
const TAGS_UNIVERSAL: Array[String] = [
|
||||||
|
"b]|[/b",
|
||||||
|
"u]|[/u",
|
||||||
|
"i]|[/i",
|
||||||
|
"s]|[/s",
|
||||||
|
"code]|[/code",
|
||||||
|
"color=|][/color",
|
||||||
|
"lb||",
|
||||||
|
"rb||",
|
||||||
|
"font=|][/font",
|
||||||
|
"img]res://|[/img",
|
||||||
|
"img width=| height=]res://[/img",
|
||||||
|
"url]|[/url",
|
||||||
|
"url=https://|][/url",
|
||||||
|
"center]|[/center",
|
||||||
|
]
|
||||||
|
const TAGS_DOC_COMMENT_REFERENCE: Array[String] = [
|
||||||
|
"annotation |",
|
||||||
|
"constant |",
|
||||||
|
"enum |",
|
||||||
|
"member |",
|
||||||
|
"method |",
|
||||||
|
"constructor |",
|
||||||
|
"operator |",
|
||||||
|
"signal |",
|
||||||
|
"theme_item |",
|
||||||
|
]
|
||||||
|
const TAGS_DOC_COMMENT_FORMATTING: Array[String] = [
|
||||||
|
"codeblock]|[/codeblock",
|
||||||
|
"br||",
|
||||||
|
"kbd]|[/kbd",
|
||||||
|
]
|
||||||
|
# TODO add all tags
|
||||||
|
const TAGS_RICH_TEXT_LABEL: Array[String] = [
|
||||||
|
# TODO complete with all options
|
||||||
|
"font name=| size=][/font]",
|
||||||
|
'url={"|": }][/url',
|
||||||
|
]
|
||||||
|
const COLORS: Array[StringName] = [
|
||||||
|
"alice_blue",
|
||||||
|
"antique_white",
|
||||||
|
"aqua",
|
||||||
|
"aquamarine",
|
||||||
|
"azure",
|
||||||
|
"beige",
|
||||||
|
"bisque",
|
||||||
|
"black",
|
||||||
|
"blanched_almond",
|
||||||
|
"blue",
|
||||||
|
"blue_violet",
|
||||||
|
"brown",
|
||||||
|
"burlywood",
|
||||||
|
"cadet_blue",
|
||||||
|
"chartreuse",
|
||||||
|
"chocolate",
|
||||||
|
"coral",
|
||||||
|
"cornflower_blue",
|
||||||
|
"cornsilk",
|
||||||
|
"crimson",
|
||||||
|
"cyan",
|
||||||
|
"dark_blue",
|
||||||
|
"dark_cyan",
|
||||||
|
"dark_goldenrod",
|
||||||
|
"dark_gray",
|
||||||
|
"dark_green",
|
||||||
|
"dark_khaki",
|
||||||
|
"dark_magenta",
|
||||||
|
"dark_olive_green",
|
||||||
|
"dark_orange",
|
||||||
|
"dark_orchid",
|
||||||
|
"dark_red",
|
||||||
|
"dark_salmon",
|
||||||
|
"dark_sea_green",
|
||||||
|
"dark_slate_blue",
|
||||||
|
"dark_slate_gray",
|
||||||
|
"dark_turquoise",
|
||||||
|
"dark_violet",
|
||||||
|
"deep_pink",
|
||||||
|
"deep_sky_blue",
|
||||||
|
"dim_gray",
|
||||||
|
"dodger_blue",
|
||||||
|
"firebrick",
|
||||||
|
"floral_white",
|
||||||
|
"forest_green",
|
||||||
|
"fuchsia",
|
||||||
|
"gainsboro",
|
||||||
|
"ghost_white",
|
||||||
|
"gold",
|
||||||
|
"goldenrod",
|
||||||
|
"gray",
|
||||||
|
"green",
|
||||||
|
"green_yellow",
|
||||||
|
"honeydew",
|
||||||
|
"hot_pink",
|
||||||
|
"indian_red",
|
||||||
|
"indigo",
|
||||||
|
"ivory",
|
||||||
|
"khaki",
|
||||||
|
"lavender",
|
||||||
|
"lavender_blush",
|
||||||
|
"lawn_green",
|
||||||
|
"lemon_chiffon",
|
||||||
|
"light_blue",
|
||||||
|
"light_coral",
|
||||||
|
"light_cyan",
|
||||||
|
"light_goldenrod",
|
||||||
|
"light_gray",
|
||||||
|
"light_green",
|
||||||
|
"light_pink",
|
||||||
|
"light_salmon",
|
||||||
|
"light_sea_green",
|
||||||
|
"light_sky_blue",
|
||||||
|
"light_slate_gray",
|
||||||
|
"light_steel_blue",
|
||||||
|
"light_yellow",
|
||||||
|
"lime",
|
||||||
|
"lime_green",
|
||||||
|
"linen",
|
||||||
|
"magenta",
|
||||||
|
"maroon",
|
||||||
|
"medium_aquamarine",
|
||||||
|
"medium_blue",
|
||||||
|
"medium_orchid",
|
||||||
|
"medium_purple",
|
||||||
|
"medium_sea_green",
|
||||||
|
"medium_slate_blue",
|
||||||
|
"medium_spring_green",
|
||||||
|
"medium_turquoise",
|
||||||
|
"medium_violet_red",
|
||||||
|
"midnight_blue",
|
||||||
|
"mint_cream",
|
||||||
|
"misty_rose",
|
||||||
|
"moccasin",
|
||||||
|
"navajo_white",
|
||||||
|
"navy_blue",
|
||||||
|
"old_lace",
|
||||||
|
"olive",
|
||||||
|
"olive_drab",
|
||||||
|
"orange",
|
||||||
|
"orange_red",
|
||||||
|
"orchid",
|
||||||
|
"pale_goldenrod",
|
||||||
|
"pale_green",
|
||||||
|
"pale_turquoise",
|
||||||
|
"pale_violet_red",
|
||||||
|
"papaya_whip",
|
||||||
|
"peach_puff",
|
||||||
|
"peru",
|
||||||
|
"pink",
|
||||||
|
"plum",
|
||||||
|
"powder_blue",
|
||||||
|
"purple",
|
||||||
|
"rebecca_purple",
|
||||||
|
"red",
|
||||||
|
"rosy_brown",
|
||||||
|
"royal_blue",
|
||||||
|
"saddle_brown",
|
||||||
|
"salmon",
|
||||||
|
"sandy_brown",
|
||||||
|
"sea_green",
|
||||||
|
"seashell",
|
||||||
|
"sienna",
|
||||||
|
"silver",
|
||||||
|
"sky_blue",
|
||||||
|
"slate_blue",
|
||||||
|
"slate_gray",
|
||||||
|
"snow",
|
||||||
|
"spring_green",
|
||||||
|
"steel_blue",
|
||||||
|
"tan",
|
||||||
|
"teal",
|
||||||
|
"thistle",
|
||||||
|
"tomato",
|
||||||
|
"transparent",
|
||||||
|
"turquoise",
|
||||||
|
"violet",
|
||||||
|
"web_gray",
|
||||||
|
"web_green",
|
||||||
|
"web_maroon",
|
||||||
|
"web_purple",
|
||||||
|
"wheat",
|
||||||
|
"white",
|
||||||
|
"white_smoke",
|
||||||
|
"yellow",
|
||||||
|
"yellow_green",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
static var _BUILTIN_CLASSES = PackedStringArray()
|
||||||
|
|
||||||
|
|
||||||
|
static func get_builtin_classes() -> PackedStringArray:
|
||||||
|
if not _BUILTIN_CLASSES:
|
||||||
|
var file: FileAccess = FileAccess.open(PATH_BUILTIN_COMPLETIONS, FileAccess.READ)
|
||||||
|
if FileAccess.get_open_error():
|
||||||
|
push_error(
|
||||||
|
"Failed to open "
|
||||||
|
+ PATH_BUILTIN_COMPLETIONS
|
||||||
|
+ ", error is:"
|
||||||
|
+ error_string(FileAccess.get_open_error())
|
||||||
|
)
|
||||||
|
_BUILTIN_CLASSES = file.get_as_text().split("\n")
|
||||||
|
return _BUILTIN_CLASSES
|
||||||
|
|
||||||
|
|
||||||
|
static var icon_cache: Dictionary = {}
|
||||||
|
static func get_class_completions() -> ClassCompletions:
|
||||||
|
var class_names: PackedStringArray = get_builtin_classes().duplicate()
|
||||||
|
var icons: Array[Texture2D] = []
|
||||||
|
for class_name_ in class_names:
|
||||||
|
icons.append(Scraper.get_builtin_class_icon(class_name_))
|
||||||
|
|
||||||
|
var classes: Array[Dictionary] = ProjectSettings.get_global_class_list()
|
||||||
|
var class_to_icon: Dictionary = {}
|
||||||
|
var class_to_base: Dictionary = {}
|
||||||
|
|
||||||
|
for class_ in classes:
|
||||||
|
var class_name_: String = class_["class"]
|
||||||
|
class_names.append(class_name_)
|
||||||
|
|
||||||
|
var icon_path: String = class_.get("icon", "")
|
||||||
|
if icon_path:
|
||||||
|
icons.append(load(icon_path))
|
||||||
|
elif class_name_ in icon_cache:
|
||||||
|
icons.append(icon_cache[class_name_])
|
||||||
|
else:
|
||||||
|
if class_to_base.is_empty():
|
||||||
|
for class__ in classes:
|
||||||
|
if class__["icon"]:
|
||||||
|
class_to_icon[class__["class"]] = class__["icon"]
|
||||||
|
class_to_base[class__["class"]] = class__["base"]
|
||||||
|
var icon_class: String = class_name_
|
||||||
|
while icon_class in class_to_base:
|
||||||
|
icon_class = class_to_base[icon_class]
|
||||||
|
if icon_class in class_to_icon:
|
||||||
|
icon_cache[class_name_] = load(class_to_icon[icon_class])
|
||||||
|
icons.append(icon_cache[class_name_])
|
||||||
|
break
|
||||||
|
if len(icons) != len(class_names):
|
||||||
|
icon_cache[class_name_] = Scraper.get_builtin_class_icon(icon_class)
|
||||||
|
icons.append(icon_cache[class_name_])
|
||||||
|
|
||||||
|
return ClassCompletions.new(
|
||||||
|
class_names,
|
||||||
|
icons,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ClassCompletions:
|
||||||
|
var names: PackedStringArray
|
||||||
|
var icons: Array[Texture2D]
|
||||||
|
|
||||||
|
func _init(_names: PackedStringArray, _icons: Array[Texture2D]) -> void:
|
||||||
|
names = _names
|
||||||
|
icons = _icons
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://cwk6mlavaqf8c
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
extends Node
|
||||||
|
|
||||||
|
|
||||||
|
## This has to be a scene.
|
||||||
|
## (In an EditorScript, editor specifc classes would polute the result)
|
||||||
|
|
||||||
|
const Completions = preload("res://addons/bbcode_edit.editor/completions_db/completions.gd")
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
print("Fetching classes...")
|
||||||
|
var file: FileAccess = FileAccess.open(Completions.PATH_BUILTIN_COMPLETIONS, FileAccess.WRITE)
|
||||||
|
if FileAccess.get_open_error():
|
||||||
|
push_error(
|
||||||
|
"Failed to open "
|
||||||
|
+ Completions.PATH_BUILTIN_COMPLETIONS
|
||||||
|
+ ", error is:"
|
||||||
|
+ error_string(FileAccess.get_open_error())
|
||||||
|
)
|
||||||
|
return
|
||||||
|
file.store_string("\n".join(ClassDB.get_class_list()))
|
||||||
|
print_rich("[color=web_green]Classes successfuly pasted to clipboard")
|
||||||
|
get_tree().quit()
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://bd4tjvv6hc3wg
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://blcco0wsttyck"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/bbcode_edit.editor/completions_db/fetch_builtin_classes.gd" id="1_tk0nj"]
|
||||||
|
|
||||||
|
[node name="FetchClassDB" type="Node"]
|
||||||
|
script = ExtResource("1_tk0nj")
|
||||||
126
source/addons/bbcode_edit.editor/editor_interface_scraper.gd
Normal file
126
source/addons/bbcode_edit.editor/editor_interface_scraper.gd
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
extends Object
|
||||||
|
|
||||||
|
|
||||||
|
## This singleton has utility methods to scrap the Editor's interface
|
||||||
|
|
||||||
|
|
||||||
|
static func get_icon(icon: StringName) -> Texture2D:
|
||||||
|
return EditorInterface.get_base_control().get_theme_icon(icon, &"EditorIcons")
|
||||||
|
|
||||||
|
|
||||||
|
static func get_color_icon() -> Texture2D:
|
||||||
|
return get_icon(&"Color")
|
||||||
|
|
||||||
|
|
||||||
|
static func get_reference_icon() -> Texture2D:
|
||||||
|
return get_icon(&"Help")
|
||||||
|
|
||||||
|
|
||||||
|
static func try_get_icon(icon: StringName, fallback: StringName) -> Texture2D:
|
||||||
|
var result: Texture2D = get_icon(icon)
|
||||||
|
if result == get_icon(&"za86e81czxe1s89az6ee7s1"): # Random
|
||||||
|
return get_icon(fallback)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
static func get_builtin_class_icon(class_name_: StringName) -> Texture2D:
|
||||||
|
var result: Texture2D = get_icon(class_name_)
|
||||||
|
var file_broken: Texture2D = get_icon(&"za86e81czxe1s89az6ee7s1") # Random
|
||||||
|
while result == file_broken and class_name_ != &"":
|
||||||
|
class_name_ = ClassDB.get_parent_class(class_name_)
|
||||||
|
result = get_icon(class_name_)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
static func get_class_icon(name: StringName, fallback: StringName) -> Texture2D:
|
||||||
|
if ClassDB.class_exists(name):
|
||||||
|
return get_builtin_class_icon(name)
|
||||||
|
var base_name = name
|
||||||
|
var global_class_list := ProjectSettings.get_global_class_list()
|
||||||
|
var found: bool = true
|
||||||
|
while found:
|
||||||
|
found = false
|
||||||
|
for class_ in global_class_list:
|
||||||
|
if class_["class"] == name:
|
||||||
|
if class_["icon"]:
|
||||||
|
return load(class_["icon"])
|
||||||
|
else:
|
||||||
|
name = class_["base"]
|
||||||
|
if ClassDB.class_exists(name):
|
||||||
|
return get_builtin_class_icon(name)
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
|
||||||
|
# This can happen for type union (ex: CanvasItemMaterial,ShaderMaterial)
|
||||||
|
return get_icon(fallback)
|
||||||
|
|
||||||
|
|
||||||
|
## [b]Note:[/b] Return the Variant icon for [constant @GlobalScope.TYPE_NIL].
|
||||||
|
static func get_builtin_type_icon(type: Variant.Type, fallback: StringName) -> Texture2D:
|
||||||
|
if type == TYPE_NIL:
|
||||||
|
return get_icon(&"Variant")
|
||||||
|
|
||||||
|
if 0 <= type and type < TYPE_MAX:
|
||||||
|
return get_icon(type_string(type))
|
||||||
|
|
||||||
|
return get_icon(fallback)
|
||||||
|
|
||||||
|
|
||||||
|
static func get_type_icon(value: Variant, fallback: StringName) -> Texture2D:
|
||||||
|
var type: int = typeof(value)
|
||||||
|
if type == TYPE_OBJECT:
|
||||||
|
if value is Script:
|
||||||
|
var to_check: Script = value
|
||||||
|
while true:
|
||||||
|
if to_check.get_global_name():
|
||||||
|
return get_class_icon(to_check.get_global_name(), fallback)
|
||||||
|
# TODO MAYBE Read first line for @icon
|
||||||
|
if to_check.get_base_script():
|
||||||
|
to_check = to_check.get_base_script()
|
||||||
|
else:
|
||||||
|
return get_builtin_class_icon(to_check.get_instance_base_type())
|
||||||
|
|
||||||
|
var script: Script = value.get_script()
|
||||||
|
if script:
|
||||||
|
var search_for: Script = script
|
||||||
|
while true:
|
||||||
|
for class_ in ProjectSettings.get_global_class_list():
|
||||||
|
if class_["path"] == search_for.resource_path:
|
||||||
|
return get_class_icon(class_["class"], fallback)
|
||||||
|
if search_for.get_base_script():
|
||||||
|
search_for = search_for.get_base_script()
|
||||||
|
else:
|
||||||
|
return get_builtin_class_icon(search_for.get_instance_base_type())
|
||||||
|
|
||||||
|
return get_builtin_class_icon(value.get_class())
|
||||||
|
|
||||||
|
return get_builtin_type_icon(type, fallback)
|
||||||
|
|
||||||
|
|
||||||
|
## Scrap the Editor tree to find if it's unsaved.
|
||||||
|
static func is_current_script_unsaved() -> bool:
|
||||||
|
# Reference path: $"../../../../../../@VSplitContainer@9820/@VBoxContainer@9821/@ItemList@9824"
|
||||||
|
var current_editor := EditorInterface.get_script_editor().get_current_editor().get_base_editor()
|
||||||
|
if current_editor is not CodeEdit:
|
||||||
|
return false
|
||||||
|
|
||||||
|
var pointer: Node = current_editor.get_node(^"../../../../../..")
|
||||||
|
|
||||||
|
if pointer == null:
|
||||||
|
return false
|
||||||
|
|
||||||
|
for node_type: String in ["VSplitContainer", "VBoxContainer", "ItemList"]:
|
||||||
|
pointer = _fetch_node(pointer, node_type)
|
||||||
|
if pointer == null:
|
||||||
|
return false
|
||||||
|
|
||||||
|
var item_list: ItemList = pointer
|
||||||
|
return item_list.get_item_text(item_list.get_selected_items()[0]).ends_with("(*)")
|
||||||
|
|
||||||
|
|
||||||
|
static func _fetch_node(parent: Node, type: String) -> Node:
|
||||||
|
type = "@" + type
|
||||||
|
for child in parent.get_children():
|
||||||
|
if child.name.begins_with(type):
|
||||||
|
return child
|
||||||
|
return null
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://dfbwqmen4hcc4
|
||||||
7
source/addons/bbcode_edit.editor/plugin.cfg
Normal file
7
source/addons/bbcode_edit.editor/plugin.cfg
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
[plugin]
|
||||||
|
|
||||||
|
name="BBCodeEdit (for script editor)"
|
||||||
|
description="A Godot addon that brings BBCode completion and QOL tools to the script editor in order to help formatting documentation comments."
|
||||||
|
author="Patou"
|
||||||
|
version="1.0.1"
|
||||||
|
script="bbcode_edit_main.gd"
|
||||||
21
source/addons/debug_draw_3d/LICENSE
Normal file
21
source/addons/debug_draw_3d/LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 DmitriySalnikov
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the Software), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, andor sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
162
source/addons/debug_draw_3d/README.md
Normal file
162
source/addons/debug_draw_3d/README.md
Normal file
@ -0,0 +1,162 @@
|
|||||||
|

|
||||||
|
|
||||||
|
# Debug drawing utility for Godot
|
||||||
|
|
||||||
|
This is an add-on for debug drawing in 3D and for some 2D overlays, which is written in `C++` and can be used with `GDScript` or `C#`.
|
||||||
|
|
||||||
|
Based on my previous addon, which was developed [only for C#](https://github.com/DmitriySalnikov/godot_debug_draw_cs), and which was inspired by [Zylann's GDScript addon](https://github.com/Zylann/godot_debug_draw)
|
||||||
|
|
||||||
|
## [Documentation](https://dd3d.dmitriysalnikov.ru/docs/)
|
||||||
|
|
||||||
|
## [Godot 3 version](https://github.com/DmitriySalnikov/godot_debug_draw_3d/tree/godot_3)
|
||||||
|
|
||||||
|
## Support me
|
||||||
|
|
||||||
|
Your support adds motivation to develop my public projects.
|
||||||
|
|
||||||
|
<a href="https://boosty.to/dmitriysalnikov/donate"><img src="/docs/images/boosty.png" alt="Boosty" width=150px/></a>
|
||||||
|
|
||||||
|
<img src="/docs/images/USDT-TRC20.png" alt="USDT-TRC20" width=150px/>
|
||||||
|
|
||||||
|
<b>USDT-TRC20 TEw934PrsffHsAn5M63SoHYRuZo984EF6v</b>
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
3D:
|
||||||
|
|
||||||
|
* Arrow
|
||||||
|
* Billboard opaque square
|
||||||
|
* Box
|
||||||
|
* Camera Frustum
|
||||||
|
* Cylinder
|
||||||
|
* Gizmo
|
||||||
|
* Grid
|
||||||
|
* Line
|
||||||
|
* Line Path
|
||||||
|
* Line with Arrow
|
||||||
|
* Plane
|
||||||
|
* Points
|
||||||
|
* Position 3D (3 crossing axes)
|
||||||
|
* Sphere
|
||||||
|
|
||||||
|
2D:
|
||||||
|
|
||||||
|
* **[Work in progress]**
|
||||||
|
|
||||||
|
Overlay:
|
||||||
|
|
||||||
|
* Text (with grouping and coloring)
|
||||||
|
* FPS Graph
|
||||||
|
* Custom Graphs
|
||||||
|
|
||||||
|
Precompiled for:
|
||||||
|
|
||||||
|
* Windows
|
||||||
|
* Linux (built on Ubuntu 20.04)
|
||||||
|
* macOS (10.14+)
|
||||||
|
* Android (5.0+)
|
||||||
|
* iOS
|
||||||
|
* Web (Firefox not supported)
|
||||||
|
|
||||||
|
This addon supports working with several World3D and different Viewports.
|
||||||
|
There is also a no depth test mode and other settings that can be changed for each instance.
|
||||||
|
|
||||||
|
This library supports double-precision builds, for more information, [see the documentation](https://dd3d.dmitriysalnikov.ru/docs/1.4.5/md_docs_2DoublePrecision.html).
|
||||||
|
|
||||||
|
## [Interactive Web Demo](https://dd3d.dmitriysalnikov.ru/demo/)
|
||||||
|
|
||||||
|
[](https://dd3d.dmitriysalnikov.ru/demo/)
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
>
|
||||||
|
> * Firefox most likely can't run this demo
|
||||||
|
|
||||||
|
## Download
|
||||||
|
|
||||||
|
To download, use the [Godot Asset Library](https://godotengine.org/asset-library/asset/1766) or use one of the stable versions from the [GitHub Releases](https://github.com/DmitriySalnikov/godot_debug_draw_3d/releases) page.
|
||||||
|
|
||||||
|
For versions prior to `1.4.5`, just download one of the `source codes` in the assets. For newer versions, download `debug-draw-3d_[version].zip`.
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
* Close editor
|
||||||
|
* Copy `addons/debug_draw_3d` to your `addons` folder, create it if the folder doesn't exist
|
||||||
|
* Launch editor
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
More examples can be found in the `examples_dd3d/` folder.
|
||||||
|
|
||||||
|
Simple test:
|
||||||
|
|
||||||
|
```gdscript
|
||||||
|
func _process(delta: float) -> void:
|
||||||
|
var _time = Time.get_ticks_msec() / 1000.0
|
||||||
|
var box_pos = Vector3(0, sin(_time * 4), 0)
|
||||||
|
var line_begin = Vector3(-1, sin(_time * 4), 0)
|
||||||
|
var line_end = Vector3(1, cos(_time * 4), 0)
|
||||||
|
|
||||||
|
DebugDraw3D.draw_box(box_pos, Vector3(1, 2, 1), Color(0, 1, 0))
|
||||||
|
DebugDraw3D.draw_line(line_begin, line_end, Color(1, 1, 0))
|
||||||
|
DebugDraw2D.set_text("Time", _time)
|
||||||
|
DebugDraw2D.set_text("Frames drawn", Engine.get_frames_drawn())
|
||||||
|
DebugDraw2D.set_text("FPS", Engine.get_frames_per_second())
|
||||||
|
DebugDraw2D.set_text("delta", delta)
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
An example of using scoped configs:
|
||||||
|
|
||||||
|
```gdscript
|
||||||
|
@tool
|
||||||
|
extends Node3D
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
# Set the base scoped_config.
|
||||||
|
# Each frame will be reset to these scoped values.
|
||||||
|
DebugDraw3D.scoped_config().set_thickness(0.1).set_center_brightness(0.6)
|
||||||
|
|
||||||
|
func _process(delta):
|
||||||
|
# Draw using the base scoped config.
|
||||||
|
DebugDraw3D.draw_box(Vector3.ZERO, Quaternion.IDENTITY, Vector3.ONE * 2, Color.CORNFLOWER_BLUE)
|
||||||
|
if true:
|
||||||
|
# Create a scoped config that will exist until exiting this if.
|
||||||
|
var _s = DebugDraw3D.new_scoped_config().set_thickness(0).set_center_brightness(0.1)
|
||||||
|
# Draw with a thickness of 0
|
||||||
|
DebugDraw3D.draw_box(Vector3.ZERO, Quaternion.IDENTITY, Vector3.ONE, Color.RED)
|
||||||
|
# If necessary, the values inside this scope can be changed
|
||||||
|
# even before each call to draw_*.
|
||||||
|
_s.set_thickness(0.05)
|
||||||
|
DebugDraw3D.draw_box(Vector3(1,0,1), Quaternion.IDENTITY, Vector3.ONE * 1, Color.BLUE_VIOLET)
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
>
|
||||||
|
> If you want to use a non-standard Viewport for rendering a 3d scene, then do not forget to specify it in the scoped config!
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
This project has a separate [documentation](https://dd3d.dmitriysalnikov.ru/docs/) page.
|
||||||
|
|
||||||
|
Also, a list of all functions is available in the documentation inside the editor (see `DebugDraw3D` and `DebugDraw2D`).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Known issues and limitations
|
||||||
|
|
||||||
|
The text in the keys and values of a text group cannot contain multi-line strings.
|
||||||
|
|
||||||
|
The entire text overlay can only be placed in one corner, unlike `DataGraphs`.
|
||||||
|
|
||||||
|
[Frustum of Camera3D does not take into account the window size from ProjectSettings](https://github.com/godotengine/godot/issues/70362).
|
||||||
|
|
||||||
|
## More screenshots
|
||||||
|
|
||||||
|
`DebugDrawDemoScene.tscn` in editor
|
||||||
|

|
||||||
|
|
||||||
|
`DebugDrawDemoScene.tscn` in play mode
|
||||||
|

|
||||||
153
source/addons/debug_draw_3d/debug_draw_3d.gdextension
Normal file
153
source/addons/debug_draw_3d/debug_draw_3d.gdextension
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
[configuration]
|
||||||
|
|
||||||
|
entry_symbol = "debug_draw_3d_library_init"
|
||||||
|
compatibility_minimum = "4.1.4"
|
||||||
|
reloadable = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
|
||||||
|
; example.x86_64 = { "relative or absolute path to the dependency" : "the path relative to the exported project", }
|
||||||
|
; -------------------------------------
|
||||||
|
; debug
|
||||||
|
|
||||||
|
macos = { }
|
||||||
|
windows.x86_64 = { }
|
||||||
|
linux.x86_64 = { }
|
||||||
|
|
||||||
|
; by default godot is using threads
|
||||||
|
web.wasm32.nothreads = {}
|
||||||
|
web.wasm32 = {}
|
||||||
|
|
||||||
|
android.arm32 = { }
|
||||||
|
android.arm64 = { }
|
||||||
|
android.x86_32 = { }
|
||||||
|
android.x86_64 = { }
|
||||||
|
|
||||||
|
ios = {}
|
||||||
|
|
||||||
|
; -------------------------------------
|
||||||
|
; release no debug draw
|
||||||
|
|
||||||
|
macos.template_release = { }
|
||||||
|
windows.template_release.x86_64 = { }
|
||||||
|
linux.template_release.x86_64 = { }
|
||||||
|
|
||||||
|
web.template_release.wasm32.nothreads = { }
|
||||||
|
web.template_release.wasm32 = { }
|
||||||
|
|
||||||
|
android.template_release.arm32 = { }
|
||||||
|
android.template_release.arm64 = { }
|
||||||
|
android.template_release.x86_32 = { }
|
||||||
|
android.template_release.x86_64 = { }
|
||||||
|
|
||||||
|
ios.template_release = {}
|
||||||
|
|
||||||
|
; -------------------------------------
|
||||||
|
; release forced debug draw
|
||||||
|
|
||||||
|
macos.template_release.forced_dd3d = { }
|
||||||
|
windows.template_release.x86_64.forced_dd3d = { }
|
||||||
|
linux.template_release.x86_64.forced_dd3d = { }
|
||||||
|
|
||||||
|
web.template_release.wasm32.nothreads.forced_dd3d = { }
|
||||||
|
web.template_release.wasm32.forced_dd3d = { }
|
||||||
|
|
||||||
|
ios.template_release.forced_dd3d = {}
|
||||||
|
|
||||||
|
[libraries]
|
||||||
|
|
||||||
|
; -------------------------------------
|
||||||
|
; debug
|
||||||
|
|
||||||
|
macos = "libs/libdd3d.macos.editor.universal.framework"
|
||||||
|
windows.x86_64 = "libs/libdd3d.windows.editor.x86_64.dll"
|
||||||
|
linux.x86_64 = "libs/libdd3d.linux.editor.x86_64.so"
|
||||||
|
|
||||||
|
web.wasm32.nothreads = "libs/libdd3d.web.template_debug.wasm32.wasm"
|
||||||
|
web.wasm32 = "libs/libdd3d.web.template_debug.wasm32.threads.wasm"
|
||||||
|
|
||||||
|
android.arm32 = "libs/libdd3d.android.template_debug.arm32.so"
|
||||||
|
android.arm64 = "libs/libdd3d.android.template_debug.arm64.so"
|
||||||
|
android.x86_32 = "libs/libdd3d.android.template_debug.x86_32.so"
|
||||||
|
android.x86_64 = "libs/libdd3d.android.template_debug.x86_64.so"
|
||||||
|
|
||||||
|
ios = "libs/libdd3d.ios.template_debug.universal.dylib"
|
||||||
|
|
||||||
|
; -------------------------------------
|
||||||
|
; release no debug draw
|
||||||
|
|
||||||
|
macos.template_release = "libs/libdd3d.macos.template_release.universal.framework"
|
||||||
|
windows.template_release.x86_64 = "libs/libdd3d.windows.template_release.x86_64.dll"
|
||||||
|
linux.template_release.x86_64 = "libs/libdd3d.linux.template_release.x86_64.so"
|
||||||
|
|
||||||
|
web.template_release.wasm32.nothreads = "libs/libdd3d.web.template_release.wasm32.wasm"
|
||||||
|
web.template_release.wasm32 = "libs/libdd3d.web.template_release.wasm32.threads.wasm"
|
||||||
|
|
||||||
|
android.template_release.arm32 = "libs/libdd3d.android.template_release.arm32.so"
|
||||||
|
android.template_release.arm64 = "libs/libdd3d.android.template_release.arm64.so"
|
||||||
|
android.template_release.x86_32 = "libs/libdd3d.android.template_release.x86_32.so"
|
||||||
|
android.template_release.x86_64 = "libs/libdd3d.android.template_release.x86_64.so"
|
||||||
|
|
||||||
|
ios.template_release = "libs/libdd3d.ios.template_release.universal.dylib"
|
||||||
|
|
||||||
|
; -------------------------------------
|
||||||
|
; release forced debug draw
|
||||||
|
|
||||||
|
macos.template_release.forced_dd3d = "libs/libdd3d.macos.template_release.universal.enabled.framework"
|
||||||
|
windows.template_release.x86_64.forced_dd3d = "libs/libdd3d.windows.template_release.x86_64.enabled.dll"
|
||||||
|
linux.template_release.x86_64.forced_dd3d = "libs/libdd3d.linux.template_release.x86_64.enabled.so"
|
||||||
|
|
||||||
|
web.template_release.wasm32.nothreads.forced_dd3d = "libs/libdd3d.web.template_release.wasm32.enabled.wasm"
|
||||||
|
web.template_release.wasm32.forced_dd3d = "libs/libdd3d.web.template_release.wasm32.threads.enabled.wasm"
|
||||||
|
|
||||||
|
ios.template_release.forced_dd3d = "libs/libdd3d.ios.template_release.universal.enabled.dylib"
|
||||||
|
|
||||||
|
; -------------------------------------
|
||||||
|
; DOUBLE PRECISION
|
||||||
|
; -------------------------------------
|
||||||
|
|
||||||
|
; -------------------------------------
|
||||||
|
; debug
|
||||||
|
|
||||||
|
macos.double = "libs/libdd3d.macos.editor.universal.double.framework"
|
||||||
|
windows.x86_64.double = "libs/libdd3d.windows.editor.x86_64.double.dll"
|
||||||
|
linux.x86_64.double = "libs/libdd3d.linux.editor.x86_64.double.so"
|
||||||
|
|
||||||
|
web.wasm32.nothreads.double = "libs/libdd3d.web.template_debug.wasm32.double.wasm"
|
||||||
|
web.wasm32.double = "libs/libdd3d.web.template_debug.wasm32.threads.double.wasm"
|
||||||
|
|
||||||
|
android.arm32.double = "libs/libdd3d.android.template_debug.arm32.double.so"
|
||||||
|
android.arm64.double = "libs/libdd3d.android.template_debug.arm64.double.so"
|
||||||
|
android.x86_32.double = "libs/libdd3d.android.template_debug.x86_32.double.so"
|
||||||
|
android.x86_64.double = "libs/libdd3d.android.template_debug.x86_64.double.so"
|
||||||
|
|
||||||
|
ios.double = "libs/libdd3d.ios.template_debug.universal.dylib"
|
||||||
|
|
||||||
|
; -------------------------------------
|
||||||
|
; release no debug draw
|
||||||
|
|
||||||
|
macos.template_release.double = "libs/libdd3d.macos.template_release.universal.double.framework"
|
||||||
|
windows.template_release.x86_64.double = "libs/libdd3d.windows.template_release.x86_64.double.dll"
|
||||||
|
linux.template_release.x86_64.double = "libs/libdd3d.linux.template_release.x86_64.double.so"
|
||||||
|
|
||||||
|
web.template_release.wasm32.nothreads.double = "libs/libdd3d.web.template_release.wasm32.double.wasm"
|
||||||
|
web.template_release.wasm32.double = "libs/libdd3d.web.template_release.wasm32.threads.double.wasm"
|
||||||
|
|
||||||
|
android.template_release.arm32.double = "libs/libdd3d.android.template_release.arm32.double.so"
|
||||||
|
android.template_release.arm64.double = "libs/libdd3d.android.template_release.arm64.double.so"
|
||||||
|
android.template_release.x86_32.double = "libs/libdd3d.android.template_release.x86_32.double.so"
|
||||||
|
android.template_release.x86_64.double = "libs/libdd3d.android.template_release.x86_64.double.so"
|
||||||
|
|
||||||
|
ios.template_release.double = "libs/libdd3d.ios.template_release.universal.double.dylib"
|
||||||
|
|
||||||
|
; -------------------------------------
|
||||||
|
; release forced debug draw
|
||||||
|
|
||||||
|
macos.template_release.forced_dd3d.double = "libs/libdd3d.macos.template_release.universal.enabled.double.framework"
|
||||||
|
windows.template_release.x86_64.forced_dd3d.double = "libs/libdd3d.windows.template_release.x86_64.enabled.double.dll"
|
||||||
|
linux.template_release.x86_64.forced_dd3d.double = "libs/libdd3d.linux.template_release.x86_64.enabled.double.so"
|
||||||
|
|
||||||
|
web.template_release.wasm32.nothreads.forced_dd3d.double = "libs/libdd3d.web.template_release.wasm32.enabled.double.wasm"
|
||||||
|
web.template_release.wasm32.forced_dd3d.double = "libs/libdd3d.web.template_release.wasm32.threads.enabled.double.wasm"
|
||||||
|
|
||||||
|
ios.template_release.forced_dd3d.double = "libs/libdd3d.ios.template_release.universal.enabled.double.dylib"
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://c0q15xk1bg0rd
|
||||||
0
source/addons/debug_draw_3d/libs/.gdignore
Normal file
0
source/addons/debug_draw_3d/libs/.gdignore
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
source/addons/debug_draw_3d/libs/libdd3d.linux.editor.x86_64.so
Normal file
BIN
source/addons/debug_draw_3d/libs/libdd3d.linux.editor.x86_64.so
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>libdd3d.macos.editor.universal.dylib</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>Debug Draw 3D</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>Debug Draw 3D</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>ru.dmitriysalnikov.dd3d</string>
|
||||||
|
<key>NSHumanReadableCopyright</key>
|
||||||
|
<string>Copyright (c) Dmitriy Salnikov.</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1.4.5</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.4.5</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>FMWK</string>
|
||||||
|
<key>CSResourcesFileMapped</key>
|
||||||
|
<true/>
|
||||||
|
<key>DTPlatformName</key>
|
||||||
|
<string>macosx</string>
|
||||||
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
<string>10.14</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
|
||||||
Binary file not shown.
@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>libdd3d.macos.template_release.universal.enabled.dylib</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>Debug Draw 3D</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>Debug Draw 3D</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>ru.dmitriysalnikov.dd3d</string>
|
||||||
|
<key>NSHumanReadableCopyright</key>
|
||||||
|
<string>Copyright (c) Dmitriy Salnikov.</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1.4.5</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.4.5</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>FMWK</string>
|
||||||
|
<key>CSResourcesFileMapped</key>
|
||||||
|
<true/>
|
||||||
|
<key>DTPlatformName</key>
|
||||||
|
<string>macosx</string>
|
||||||
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
<string>10.14</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
|
||||||
Binary file not shown.
@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>libdd3d.macos.template_release.universal.dylib</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>Debug Draw 3D</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>Debug Draw 3D</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>ru.dmitriysalnikov.dd3d</string>
|
||||||
|
<key>NSHumanReadableCopyright</key>
|
||||||
|
<string>Copyright (c) Dmitriy Salnikov.</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1.4.5</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.4.5</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>FMWK</string>
|
||||||
|
<key>CSResourcesFileMapped</key>
|
||||||
|
<true/>
|
||||||
|
<key>DTPlatformName</key>
|
||||||
|
<string>macosx</string>
|
||||||
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
<string>10.14</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
88
source/addons/logger/logger.gd
Normal file
88
source/addons/logger/logger.gd
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
extends CanvasLayer
|
||||||
|
|
||||||
|
enum ErrTypes { NORMAL, NORMAL_RICH, WARNING, ERROR }
|
||||||
|
|
||||||
|
const DEFAULT_DURATION: float = 5.0
|
||||||
|
|
||||||
|
@export_range(0, 1000, 1) var log_limit: int = 120
|
||||||
|
|
||||||
|
var msg_list: PackedStringArray = []
|
||||||
|
var msg_uid: PackedInt32Array = []
|
||||||
|
|
||||||
|
@onready var log_label: RichTextLabel = $LogLabel
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
if OS.has_feature("standalone"):
|
||||||
|
hide()
|
||||||
|
|
||||||
|
|
||||||
|
func print_msg(text: String, duration: float = DEFAULT_DURATION, type: ErrTypes = ErrTypes.NORMAL, color := Color.AQUA) -> void:
|
||||||
|
if not OS.is_debug_build():
|
||||||
|
return
|
||||||
|
|
||||||
|
if msg_list.size() + 1 > log_limit:
|
||||||
|
if msg_list.is_empty(): # Don't do anything if the [param log_limit] is set to 0.
|
||||||
|
return
|
||||||
|
else: # Remove the first messages until we have a free slot.
|
||||||
|
msg_list.remove_at(0)
|
||||||
|
msg_uid.remove_at(0)
|
||||||
|
print_msg(text, duration, type, color)
|
||||||
|
return
|
||||||
|
|
||||||
|
var prefix: String = ""
|
||||||
|
match type:
|
||||||
|
ErrTypes.NORMAL_RICH:
|
||||||
|
print_rich(text)
|
||||||
|
ErrTypes.WARNING:
|
||||||
|
push_warning(text)
|
||||||
|
prefix = str("[color=orange][b]WARNING: [/b][/color]")
|
||||||
|
ErrTypes.ERROR:
|
||||||
|
push_error(text)
|
||||||
|
printerr(text)
|
||||||
|
prefix = str("[color=red][b]ERROR: [/b][/color]")
|
||||||
|
|
||||||
|
# print messages into the log first before stoppingQ.
|
||||||
|
if OS.has_feature("standalone"):
|
||||||
|
return
|
||||||
|
|
||||||
|
text = str("%s[color=%s]%s[/color]" %[prefix, color.to_html(), text])
|
||||||
|
msg_list.append(text)
|
||||||
|
|
||||||
|
var timer := Timer.new()
|
||||||
|
timer.one_shot = true
|
||||||
|
|
||||||
|
msg_uid.append(absi(timer.get_instance_id()))
|
||||||
|
|
||||||
|
timer.timeout.connect(func() -> void:
|
||||||
|
var uid: int = msg_uid.find(absi(timer.get_instance_id()))
|
||||||
|
if uid >= 0:
|
||||||
|
msg_list.remove_at(uid)
|
||||||
|
msg_uid.remove_at(uid)
|
||||||
|
_update_hud()
|
||||||
|
timer.queue_free()
|
||||||
|
)
|
||||||
|
add_child(timer)
|
||||||
|
timer.start(duration if duration >= 0.0 else DEFAULT_DURATION)
|
||||||
|
|
||||||
|
_update_hud()
|
||||||
|
|
||||||
|
|
||||||
|
func clear_log() -> void:
|
||||||
|
msg_list.clear()
|
||||||
|
msg_uid.clear()
|
||||||
|
_update_hud()
|
||||||
|
# Remove the timers.
|
||||||
|
for i: Node in get_children():
|
||||||
|
if not i == log_label:
|
||||||
|
i.queue_free()
|
||||||
|
|
||||||
|
|
||||||
|
func _update_hud() -> void:
|
||||||
|
if not self.is_node_ready():
|
||||||
|
await self.ready
|
||||||
|
|
||||||
|
var text: String = "\n".join(msg_list) if not msg_list.is_empty() else ""
|
||||||
|
log_label.set_text(text)
|
||||||
|
if msg_list.is_empty():
|
||||||
|
log_label.clear()
|
||||||
1
source/addons/logger/logger.gd.uid
Normal file
1
source/addons/logger/logger.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://b5b7ohheyhxr0
|
||||||
31
source/addons/logger/logger.tscn
Normal file
31
source/addons/logger/logger.tscn
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://cpfunq8fyixco"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" uid="uid://b5b7ohheyhxr0" path="res://addons/logger/logger.gd" id="1_thwo5"]
|
||||||
|
|
||||||
|
[node name="Logger" type="CanvasLayer"]
|
||||||
|
process_mode = 3
|
||||||
|
layer = 128
|
||||||
|
follow_viewport_enabled = true
|
||||||
|
script = ExtResource("1_thwo5")
|
||||||
|
log_limit = 30
|
||||||
|
|
||||||
|
[node name="LogLabel" type="RichTextLabel" parent="."]
|
||||||
|
modulate = Color(1, 1, 1, 0.498039)
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
size_flags_vertical = 3
|
||||||
|
mouse_filter = 2
|
||||||
|
theme_override_colors/font_shadow_color = Color(0, 0, 0, 1)
|
||||||
|
theme_override_font_sizes/bold_italics_font_size = 12
|
||||||
|
theme_override_font_sizes/italics_font_size = 12
|
||||||
|
theme_override_font_sizes/mono_font_size = 12
|
||||||
|
theme_override_font_sizes/normal_font_size = 12
|
||||||
|
theme_override_font_sizes/bold_font_size = 12
|
||||||
|
bbcode_enabled = true
|
||||||
|
fit_content = true
|
||||||
|
scroll_active = false
|
||||||
|
drag_and_drop_selection_enabled = false
|
||||||
7
source/addons/logger/plugin.cfg
Normal file
7
source/addons/logger/plugin.cfg
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
[plugin]
|
||||||
|
|
||||||
|
name="On-Screen Logger - Pixelation Games"
|
||||||
|
description="A logger that automatically displays the information on the game screen for a set or given amount of time"
|
||||||
|
author="SchimmelSpreu83"
|
||||||
|
version="0.5.0"
|
||||||
|
script="plugin.gd"
|
||||||
10
source/addons/logger/plugin.gd
Normal file
10
source/addons/logger/plugin.gd
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
@tool
|
||||||
|
extends EditorPlugin
|
||||||
|
|
||||||
|
|
||||||
|
func _enable_plugin() -> void:
|
||||||
|
add_autoload_singleton("Logger", "res://addons/logger/logger.tscn")
|
||||||
|
|
||||||
|
|
||||||
|
func _disable_plugin() -> void:
|
||||||
|
remove_autoload_singleton("Logger")
|
||||||
1
source/addons/logger/plugin.gd.uid
Normal file
1
source/addons/logger/plugin.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://p6f8m3u0e8du
|
||||||
1
source/addons/panku_console/COMMIT_SHA
Normal file
1
source/addons/panku_console/COMMIT_SHA
Normal file
@ -0,0 +1 @@
|
|||||||
|
3f4fa8737ead98dec6e3c296fe1fac9bc9c397c1
|
||||||
20
source/addons/panku_console/LICENSE
Normal file
20
source/addons/panku_console/LICENSE
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2023 Feo (k2kra) Wu
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
1
source/addons/panku_console/README.md
Normal file
1
source/addons/panku_console/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
This repository is a mirror that tracks the latest version of [PankuConsole](https://github.com/Ark2000/PankuConsole), so you can add it as a submodule in you addons folder.
|
||||||
35
source/addons/panku_console/common/buffered_rich_text.gd
Normal file
35
source/addons/panku_console/common/buffered_rich_text.gd
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
extends VBoxContainer
|
||||||
|
|
||||||
|
# it is like, an infinite scroll game.
|
||||||
|
|
||||||
|
# specifically, the first buffer will be cleared and sent to the last
|
||||||
|
# when the last buffer is full.
|
||||||
|
|
||||||
|
# with buffers, we can constanly output lots of fancy stuff while keeping a smooth experience.
|
||||||
|
|
||||||
|
const BUFFER_MAX_PARAGRAPHS = 64
|
||||||
|
const BUFFERS = 4
|
||||||
|
|
||||||
|
var cur_label_idx:int = 0
|
||||||
|
|
||||||
|
func add_text(text:String):
|
||||||
|
var cur_label:RichTextLabel = get_child(cur_label_idx)
|
||||||
|
cur_label.text += text
|
||||||
|
if cur_label.get_paragraph_count() > BUFFER_MAX_PARAGRAPHS:
|
||||||
|
cur_label_idx += 1
|
||||||
|
if cur_label_idx == BUFFERS:
|
||||||
|
cur_label_idx = BUFFERS - 1
|
||||||
|
var first_label:RichTextLabel = get_child(0)
|
||||||
|
first_label.text = ""
|
||||||
|
move_child(first_label, BUFFERS - 1)
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
set("theme_override_constants/separation", 0)
|
||||||
|
for child in get_children():
|
||||||
|
child.queue_free()
|
||||||
|
for i in range(BUFFERS):
|
||||||
|
var new_buffer:RichTextLabel = RichTextLabel.new()
|
||||||
|
new_buffer.fit_content = true
|
||||||
|
new_buffer.bbcode_enabled = true
|
||||||
|
new_buffer.selection_enabled = true
|
||||||
|
add_child(new_buffer)
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://dqbh0mtduoa3k
|
||||||
37
source/addons/panku_console/common/config.gd
Normal file
37
source/addons/panku_console/common/config.gd
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
class_name PankuConfig
|
||||||
|
|
||||||
|
const USER_CONFIG_FILE_PATH = "user://panku_config.cfg"
|
||||||
|
|
||||||
|
# load config from file, always return a dictionary
|
||||||
|
static func _get_config(file_path:String) -> Dictionary:
|
||||||
|
if FileAccess.file_exists(file_path):
|
||||||
|
var file = FileAccess.open(file_path, FileAccess.READ)
|
||||||
|
var content := file.get_as_text()
|
||||||
|
var config:Dictionary = str_to_var(content)
|
||||||
|
if config: return config
|
||||||
|
return {}
|
||||||
|
|
||||||
|
# save user config to file
|
||||||
|
static func set_config(config:Dictionary):
|
||||||
|
var file = FileAccess.open(USER_CONFIG_FILE_PATH, FileAccess.WRITE)
|
||||||
|
var content = var_to_str(config)
|
||||||
|
file.store_string(content)
|
||||||
|
|
||||||
|
# get config, if user config exists, return user config, otherwise return default config configured by plugin user
|
||||||
|
static func get_config() -> Dictionary:
|
||||||
|
var user_config:Dictionary = _get_config(USER_CONFIG_FILE_PATH)
|
||||||
|
if not user_config.is_empty():
|
||||||
|
return user_config
|
||||||
|
# if no user config, return default config, which is read-only
|
||||||
|
if PankuConsolePlugin.is_custom_default_config_exists():
|
||||||
|
return _get_config(PankuConsolePlugin.get_custom_default_config_path())
|
||||||
|
|
||||||
|
return _get_config(PankuConsolePlugin.INITIAL_DEFAULT_CONFIG_FILE_PATH)
|
||||||
|
|
||||||
|
static func get_value(key:String, default:Variant) -> Variant:
|
||||||
|
return get_config().get(key, default)
|
||||||
|
|
||||||
|
static func set_value(key:String, val:Variant) -> void:
|
||||||
|
var config = _get_config(USER_CONFIG_FILE_PATH)
|
||||||
|
config[key] = val
|
||||||
|
set_config(config)
|
||||||
1
source/addons/panku_console/common/config.gd.uid
Normal file
1
source/addons/panku_console/common/config.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://bgc3h0yuqrdnt
|
||||||
276
source/addons/panku_console/common/gdexprenv.gd
Normal file
276
source/addons/panku_console/common/gdexprenv.gd
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
class_name PankuGDExprEnv
|
||||||
|
|
||||||
|
const type_names = {
|
||||||
|
TYPE_NIL: "null",
|
||||||
|
TYPE_BOOL: "bool",
|
||||||
|
TYPE_INT: "int",
|
||||||
|
TYPE_FLOAT: "float",
|
||||||
|
TYPE_STRING: "String",
|
||||||
|
TYPE_VECTOR2: "Vector2",
|
||||||
|
TYPE_VECTOR2I: "Vector2i",
|
||||||
|
TYPE_RECT2: "Rect2",
|
||||||
|
TYPE_RECT2I: "Rect2i",
|
||||||
|
TYPE_VECTOR3: "Vector3",
|
||||||
|
TYPE_VECTOR3I: "Vector3i",
|
||||||
|
TYPE_TRANSFORM2D: "Transform2D",
|
||||||
|
TYPE_VECTOR4: "Vector4",
|
||||||
|
TYPE_VECTOR4I: "Vector4i",
|
||||||
|
TYPE_PLANE: "Plane",
|
||||||
|
TYPE_QUATERNION: "Quaternion",
|
||||||
|
TYPE_AABB: "AABB",
|
||||||
|
TYPE_BASIS: "Basis",
|
||||||
|
TYPE_TRANSFORM3D: "Transform3D",
|
||||||
|
TYPE_PROJECTION: "Projection",
|
||||||
|
TYPE_COLOR: "Color",
|
||||||
|
TYPE_STRING_NAME: "StringName",
|
||||||
|
TYPE_NODE_PATH: "NodePath",
|
||||||
|
TYPE_RID: "RID",
|
||||||
|
TYPE_OBJECT: "Object",
|
||||||
|
TYPE_CALLABLE: "Callable",
|
||||||
|
TYPE_SIGNAL: "Signal",
|
||||||
|
TYPE_DICTIONARY: "Dictionary",
|
||||||
|
TYPE_ARRAY: "Array",
|
||||||
|
TYPE_PACKED_BYTE_ARRAY: "PackedByteArray",
|
||||||
|
TYPE_PACKED_INT32_ARRAY: "PackedInt32Array",
|
||||||
|
TYPE_PACKED_INT64_ARRAY: "PackedInt64Array",
|
||||||
|
TYPE_PACKED_FLOAT32_ARRAY: "PackedFloat32Array",
|
||||||
|
TYPE_PACKED_FLOAT64_ARRAY: "PackedFloat64Array",
|
||||||
|
TYPE_PACKED_STRING_ARRAY: "PackedStringArray",
|
||||||
|
TYPE_PACKED_VECTOR2_ARRAY: "PackedVector2Array",
|
||||||
|
TYPE_PACKED_VECTOR3_ARRAY: "PackedVector3Array",
|
||||||
|
TYPE_PACKED_COLOR_ARRAY: "PackedColorArray",
|
||||||
|
}
|
||||||
|
|
||||||
|
var _envs = {}
|
||||||
|
var _envs_info = {}
|
||||||
|
var _expression = Expression.new()
|
||||||
|
var _base_instance:Object
|
||||||
|
|
||||||
|
func set_base_instance(base_instance:Object):
|
||||||
|
_base_instance = base_instance
|
||||||
|
#add info of base instance
|
||||||
|
var env_info = extract_info_from_script(_base_instance.get_script())
|
||||||
|
for k in env_info: _envs_info[k] = env_info[k]
|
||||||
|
|
||||||
|
func get_base_instance():
|
||||||
|
return _base_instance
|
||||||
|
|
||||||
|
## Register an environment that run expressions.
|
||||||
|
## [br][code]env_name[/code]: the name of the environment
|
||||||
|
## [br][code]env[/code]: The base instance that runs the expressions. For exmaple your player node.
|
||||||
|
func register_env(env_name:String, env:Object):
|
||||||
|
_envs[env_name] = env
|
||||||
|
# output("[color=green][Info][/color] [b]%s[/b] env loaded!"%env_name)
|
||||||
|
if env is Node:
|
||||||
|
env.tree_exiting.connect(
|
||||||
|
func(): remove_env(env_name)
|
||||||
|
)
|
||||||
|
if env.get_script():
|
||||||
|
var env_info = extract_info_from_script(env.get_script())
|
||||||
|
for k in env_info:
|
||||||
|
var keyword = "%s.%s" % [env_name, k]
|
||||||
|
_envs_info[keyword] = env_info[k]
|
||||||
|
|
||||||
|
## Return the environment object or [code]null[/code] by its name.
|
||||||
|
func get_env(env_name:String) -> Node:
|
||||||
|
return _envs.get(env_name)
|
||||||
|
|
||||||
|
## Remove the environment named [code]env_name[/code]
|
||||||
|
func remove_env(env_name:String):
|
||||||
|
if _envs.has(env_name):
|
||||||
|
_envs.erase(env_name)
|
||||||
|
for k in _envs_info.keys():
|
||||||
|
if k.begins_with(env_name + "."):
|
||||||
|
_envs_info.erase(k)
|
||||||
|
|
||||||
|
#Execute an expression in a preset environment.
|
||||||
|
func execute(exp:String) -> Dictionary:
|
||||||
|
return execute_exp(exp, _expression, _base_instance, _envs)
|
||||||
|
|
||||||
|
# TODO: not used
|
||||||
|
func get_available_export_objs() -> Array:
|
||||||
|
var result = []
|
||||||
|
for obj_name in _envs:
|
||||||
|
var obj = _envs[obj_name]
|
||||||
|
if !obj.get_script():
|
||||||
|
continue
|
||||||
|
var export_properties = get_export_properties_from_script(obj.get_script())
|
||||||
|
if export_properties.is_empty():
|
||||||
|
continue
|
||||||
|
result.push_back(obj_name)
|
||||||
|
return result
|
||||||
|
|
||||||
|
func get_help_info(k:String) -> String:
|
||||||
|
return _envs_info[k]["help"]
|
||||||
|
|
||||||
|
#TODO: refactor all those mess
|
||||||
|
func parse_exp(exp:String, allow_empty:=false):
|
||||||
|
var result:Array
|
||||||
|
var empty_flag = allow_empty and exp.is_empty()
|
||||||
|
|
||||||
|
if empty_flag:
|
||||||
|
result = _envs_info.keys()
|
||||||
|
else:
|
||||||
|
result = search_and_sort_and_highlight(exp, _envs_info.keys())
|
||||||
|
|
||||||
|
var hints_bbcode = []
|
||||||
|
var hints_value = []
|
||||||
|
|
||||||
|
for r in result:
|
||||||
|
var keyword:String
|
||||||
|
var bbcode_main:String
|
||||||
|
|
||||||
|
if empty_flag:
|
||||||
|
keyword = r
|
||||||
|
bbcode_main = r
|
||||||
|
else:
|
||||||
|
keyword = r["keyword"]
|
||||||
|
bbcode_main = r["bbcode"]
|
||||||
|
|
||||||
|
var bbcode_postfix = _envs_info[keyword]["bbcode_postfix"]
|
||||||
|
var keyword_type = _envs_info[keyword]["type"]
|
||||||
|
hints_value.push_back(keyword)
|
||||||
|
hints_bbcode.push_back(bbcode_main + bbcode_postfix)
|
||||||
|
return {
|
||||||
|
"hints_bbcode": hints_bbcode,
|
||||||
|
"hints_value": hints_value
|
||||||
|
}
|
||||||
|
|
||||||
|
static func search_and_sort_and_highlight(s:String, li:Array):
|
||||||
|
s = s.lstrip(" ").rstrip(" ")
|
||||||
|
var matched = []
|
||||||
|
if s == "": return matched
|
||||||
|
for k in li:
|
||||||
|
var start = k.find(s)
|
||||||
|
if start >= 0:
|
||||||
|
var similarity = 1.0 * s.length() / k.length()
|
||||||
|
matched.append({
|
||||||
|
"keyword": k,
|
||||||
|
"similarity": similarity,
|
||||||
|
"start": start,
|
||||||
|
"bbcode": ""
|
||||||
|
})
|
||||||
|
|
||||||
|
matched.sort_custom(
|
||||||
|
func(k1, k2):
|
||||||
|
if k1["start"] != k2["start"]:
|
||||||
|
return k1["start"] > k2["start"]
|
||||||
|
else:
|
||||||
|
return k1["similarity"] < k2["similarity"]
|
||||||
|
)
|
||||||
|
|
||||||
|
var line_format = "%s[color=green][b]%s[/b][/color]%s"
|
||||||
|
|
||||||
|
for m in matched:
|
||||||
|
var p = ["", "", ""]
|
||||||
|
if m["start"] < 0:
|
||||||
|
p[0] = m["keyword"]
|
||||||
|
else:
|
||||||
|
p[0] = m["keyword"].substr(0, m["start"])
|
||||||
|
p[1] = s
|
||||||
|
p[2] = m["keyword"].substr(m["start"] + s.length(), -1)
|
||||||
|
|
||||||
|
m["bbcode"] = line_format % p
|
||||||
|
|
||||||
|
return matched
|
||||||
|
|
||||||
|
static func extract_info_from_script(script:Script):
|
||||||
|
var result = {}
|
||||||
|
|
||||||
|
var methods = []
|
||||||
|
var properties = []
|
||||||
|
var constants = []
|
||||||
|
var constants_bbcode_postfix = {}
|
||||||
|
|
||||||
|
for m in script.get_script_method_list():
|
||||||
|
if m["name"] != "" and m["name"].is_valid_identifier() and !m["name"].begins_with("_"):
|
||||||
|
var args = []
|
||||||
|
for a in m["args"]:
|
||||||
|
args.push_back("[color=cyan]%s[/color][color=gray]:[/color][color=orange]%s[/color]"%[a["name"], type_names[a["type"]]])
|
||||||
|
result[m["name"]] = {
|
||||||
|
"type": "method",
|
||||||
|
"bbcode_postfix": "(%s)"%("[color=gray], [/color]".join(PackedStringArray(args)))
|
||||||
|
}
|
||||||
|
for p in script.get_script_property_list():
|
||||||
|
if p["name"] != "" and !p["name"].begins_with("_") and p["name"].is_valid_identifier():
|
||||||
|
result[p["name"]] = {
|
||||||
|
"type": "property",
|
||||||
|
"bbcode_postfix":"[color=gray]:[/color][color=orange]%s[/color]"%type_names[p["type"]]
|
||||||
|
}
|
||||||
|
|
||||||
|
var constant_map = script.get_script_constant_map()
|
||||||
|
var help_info = {}
|
||||||
|
for c in constant_map:
|
||||||
|
if !c.begins_with("_"):
|
||||||
|
result[c] = {
|
||||||
|
"type": "constant",
|
||||||
|
"bbcode_postfix":"[color=gray]:[/color][color=orange]%s[/color]"%type_names[typeof(constant_map[c])]
|
||||||
|
}
|
||||||
|
elif c.begins_with("_HELP_") and c.length() > 6 and typeof(constant_map[c]) == TYPE_STRING:
|
||||||
|
var key = c.lstrip("_HELP_")
|
||||||
|
help_info[key] = constant_map[c]
|
||||||
|
|
||||||
|
for k in result:
|
||||||
|
if help_info.has(k):
|
||||||
|
result[k]["help"] = help_info[k]
|
||||||
|
else:
|
||||||
|
result[k]["help"] = "No help information provided."
|
||||||
|
|
||||||
|
#keyword -> {type, bbcode_postfix, help}
|
||||||
|
return result
|
||||||
|
|
||||||
|
static func execute_exp(exp_str:String, expression:Expression, base_instance:Object, env:Dictionary):
|
||||||
|
var failed := false
|
||||||
|
var result = null
|
||||||
|
|
||||||
|
var error = expression.parse(exp_str, env.keys())
|
||||||
|
if error != OK:
|
||||||
|
failed = true
|
||||||
|
result = expression.get_error_text()
|
||||||
|
else:
|
||||||
|
result = expression.execute(env.values(), base_instance, true)
|
||||||
|
if expression.has_execute_failed():
|
||||||
|
failed = true
|
||||||
|
result = expression.get_error_text()
|
||||||
|
|
||||||
|
return {
|
||||||
|
"failed": failed,
|
||||||
|
"result": result
|
||||||
|
}
|
||||||
|
|
||||||
|
static func get_export_properties_from_script(script:Script):
|
||||||
|
var result = []
|
||||||
|
var data = script.get_script_property_list()
|
||||||
|
for d in data:
|
||||||
|
if !(d.usage == PROPERTY_USAGE_SCRIPT_VARIABLE | PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_STORAGE):
|
||||||
|
continue
|
||||||
|
result.append(d)
|
||||||
|
return result
|
||||||
|
|
||||||
|
static func generate_help_text_from_script(script:Script):
|
||||||
|
var result = ["[color=cyan][b]User script defined identifiers[/b][/color]: "]
|
||||||
|
var env_info = extract_info_from_script(script)
|
||||||
|
var keys = env_info.keys()
|
||||||
|
keys.sort()
|
||||||
|
for k in keys:
|
||||||
|
result.push_back("%s - [i]%s[/i]"%[k + env_info[k]["bbcode_postfix"], env_info[k]["help"]])
|
||||||
|
return "\n".join(PackedStringArray(result))
|
||||||
|
|
||||||
|
#returns a string containing all public script properties of an object
|
||||||
|
#please BE AWARE when using this function on an object with custom getters.
|
||||||
|
static func get_object_outline(obj:Object) -> String:
|
||||||
|
var result := PackedStringArray()
|
||||||
|
if obj == null: return "null"
|
||||||
|
var script = obj.get_script()
|
||||||
|
if script == null:
|
||||||
|
return "this object has no script attached."
|
||||||
|
var properties = script.get_script_property_list()
|
||||||
|
for p in properties:
|
||||||
|
if p.usage & PROPERTY_USAGE_SCRIPT_VARIABLE == 0:
|
||||||
|
continue
|
||||||
|
if p.name.begins_with("_"):
|
||||||
|
continue
|
||||||
|
result.append("%s: %s" % [p.name, str(obj.get(p.name))])
|
||||||
|
if result.is_empty():
|
||||||
|
return "this object has no public script variables."
|
||||||
|
return "\n".join(result)
|
||||||
1
source/addons/panku_console/common/gdexprenv.gd.uid
Normal file
1
source/addons/panku_console/common/gdexprenv.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://cv7potpg6dris
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
extends Panel
|
||||||
|
|
||||||
|
func hey_i_am_here():
|
||||||
|
modulate.a = 0.0
|
||||||
|
var t = create_tween()
|
||||||
|
t.set_speed_scale(1.0 / Engine.time_scale)
|
||||||
|
for i in range(2):
|
||||||
|
t.tween_property(self, "modulate:a", 0.3, 0.1)
|
||||||
|
t.tween_property(self, "modulate:a", 0.0, 0.1)
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://djg7feld7wktp
|
||||||
300
source/addons/panku_console/common/lynx_window2/lynx_window_2.gd
Normal file
300
source/addons/panku_console/common/lynx_window2/lynx_window_2.gd
Normal file
@ -0,0 +1,300 @@
|
|||||||
|
class_name PankuLynxWindow extends ColorRect
|
||||||
|
|
||||||
|
#Do not connect the button node directly, use these signals to detect click event.
|
||||||
|
signal title_btn_clicked
|
||||||
|
signal window_closed
|
||||||
|
|
||||||
|
const lynx_window_shader_material:ShaderMaterial = preload("./lynx_window_shader_material.tres")
|
||||||
|
|
||||||
|
@export var _window_title_container:HBoxContainer
|
||||||
|
@export var _title_btn:PankuButton
|
||||||
|
@export var _close_btn:PankuButton
|
||||||
|
@export var _options_btn:PankuButton
|
||||||
|
@export var _resize_btn:Button
|
||||||
|
@export var _shadow_focus:Panel
|
||||||
|
@export var _shadow:NinePatchRect
|
||||||
|
@export var _container:Panel
|
||||||
|
@export var _pop_btn:PankuButton
|
||||||
|
|
||||||
|
@export var no_resize := false
|
||||||
|
@export var no_resize_x := false
|
||||||
|
@export var no_resize_y := false
|
||||||
|
@export var no_move := false
|
||||||
|
@export var no_snap := false
|
||||||
|
|
||||||
|
@export var no_title := false:
|
||||||
|
set(v):
|
||||||
|
no_title = v
|
||||||
|
_window_title_container.visible = !v
|
||||||
|
|
||||||
|
@export var queue_free_on_close := true
|
||||||
|
@export var flicker := true
|
||||||
|
|
||||||
|
var transform_interp_speed := 40.0
|
||||||
|
var bounds_interp_speed := 50.0
|
||||||
|
var anim_interp_speed := 10.0
|
||||||
|
|
||||||
|
var _is_dragging := false
|
||||||
|
var _drag_start_position:Vector2
|
||||||
|
var _drag_start_position_global:Vector2
|
||||||
|
var _is_resizing := false
|
||||||
|
var _resize_start_position:Vector2
|
||||||
|
var _os_window:Window
|
||||||
|
var _content:Control
|
||||||
|
var _size_before_folded:Vector2
|
||||||
|
var _folded:bool = false
|
||||||
|
var _size_animation:bool = false
|
||||||
|
var _target_size:Vector2
|
||||||
|
|
||||||
|
func add_options_button(callback:Callable):
|
||||||
|
_options_btn.show()
|
||||||
|
_options_btn.pressed.connect(callback)
|
||||||
|
|
||||||
|
func get_layout_position(layout:Control.LayoutPreset) -> Vector2:
|
||||||
|
var window_rect = get_rect()
|
||||||
|
var screen_rect = get_viewport_rect()
|
||||||
|
var new_position = Vector2.ZERO
|
||||||
|
var end_position = screen_rect.size - window_rect.size
|
||||||
|
var center_position = end_position / 2
|
||||||
|
if layout == PRESET_TOP_LEFT:
|
||||||
|
pass
|
||||||
|
elif layout == PRESET_CENTER_TOP:
|
||||||
|
new_position.x = center_position.x
|
||||||
|
elif layout == PRESET_TOP_RIGHT:
|
||||||
|
new_position.x = end_position.x
|
||||||
|
elif layout == PRESET_CENTER_LEFT:
|
||||||
|
new_position.y = center_position.y
|
||||||
|
elif layout == PRESET_CENTER:
|
||||||
|
new_position = center_position
|
||||||
|
elif layout == PRESET_CENTER_RIGHT:
|
||||||
|
new_position.x = end_position.x
|
||||||
|
new_position.y = center_position.y
|
||||||
|
elif layout == PRESET_BOTTOM_LEFT:
|
||||||
|
new_position.y = end_position.y
|
||||||
|
elif layout == PRESET_CENTER_BOTTOM:
|
||||||
|
new_position.x = center_position.x
|
||||||
|
new_position.y = end_position.y
|
||||||
|
elif layout == PRESET_BOTTOM_RIGHT:
|
||||||
|
new_position = end_position
|
||||||
|
return new_position
|
||||||
|
|
||||||
|
func get_content():
|
||||||
|
return _content
|
||||||
|
|
||||||
|
func set_content(node:Control):
|
||||||
|
_content = node
|
||||||
|
if _os_window and _os_window.visible:
|
||||||
|
if _os_window.get_child_count() > 0:
|
||||||
|
push_error("Error: error in set_content")
|
||||||
|
return
|
||||||
|
_os_window.add_child(node)
|
||||||
|
return
|
||||||
|
if _container.get_child_count() > 0:
|
||||||
|
push_error("Error: error in set_content.")
|
||||||
|
return
|
||||||
|
_container.add_child(node)
|
||||||
|
|
||||||
|
func highlight(v:bool):
|
||||||
|
_shadow_focus.visible = v
|
||||||
|
|
||||||
|
func _init_os_window():
|
||||||
|
_os_window = Window.new()
|
||||||
|
var color_rect = ColorRect.new()
|
||||||
|
color_rect.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||||
|
_os_window.add_child(color_rect)
|
||||||
|
get_tree().root.add_child(_os_window)
|
||||||
|
#destructor
|
||||||
|
tree_exiting.connect(
|
||||||
|
func():
|
||||||
|
_os_window.queue_free()
|
||||||
|
)
|
||||||
|
#switch back to embed window when os window close requested
|
||||||
|
_os_window.close_requested.connect(
|
||||||
|
func():
|
||||||
|
_os_window.remove_child(_content)
|
||||||
|
_os_window.hide()
|
||||||
|
set_content(_content)
|
||||||
|
show()
|
||||||
|
)
|
||||||
|
if get_parent().has_method("get_os_window_bg_color"):
|
||||||
|
color_rect.color = get_parent().get_os_window_bg_color()
|
||||||
|
|
||||||
|
func switch_to_os_window():
|
||||||
|
if _content == null:
|
||||||
|
push_error("Error: No content. ")
|
||||||
|
return
|
||||||
|
if _os_window == null:
|
||||||
|
_init_os_window()
|
||||||
|
_container.remove_child(_content)
|
||||||
|
_os_window.add_child(_content)
|
||||||
|
_os_window.size = size
|
||||||
|
_os_window.title = _title_btn.text
|
||||||
|
_os_window.position = Vector2(DisplayServer.window_get_position(0)) + position
|
||||||
|
_content.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||||
|
_os_window.show()
|
||||||
|
hide()
|
||||||
|
|
||||||
|
func show_window():
|
||||||
|
if _os_window and _os_window.visible:
|
||||||
|
return
|
||||||
|
show()
|
||||||
|
move_to_front()
|
||||||
|
modulate.a = 0.0
|
||||||
|
create_tween().tween_property(self, "modulate:a", 1.0, 0.2)
|
||||||
|
|
||||||
|
func hide_window():
|
||||||
|
if _os_window and _os_window.visible:
|
||||||
|
_os_window.close_requested.emit()
|
||||||
|
hide()
|
||||||
|
|
||||||
|
func toggle_window_visibility():
|
||||||
|
if _os_window.visible or visible:
|
||||||
|
hide_window()
|
||||||
|
else:
|
||||||
|
show_window()
|
||||||
|
|
||||||
|
func set_window_visibility(b:bool):
|
||||||
|
if b: show_window()
|
||||||
|
else: hide_window()
|
||||||
|
|
||||||
|
func get_window_visibility() -> bool:
|
||||||
|
return visible or _os_window.visible
|
||||||
|
|
||||||
|
func set_window_title_text(text:String):
|
||||||
|
if _os_window and _os_window.visible:
|
||||||
|
_os_window.title = text
|
||||||
|
else:
|
||||||
|
_title_btn.text = " " + text
|
||||||
|
|
||||||
|
func get_normal_window_size():
|
||||||
|
if _folded: return _size_before_folded
|
||||||
|
return size
|
||||||
|
|
||||||
|
func get_title_bar_height():
|
||||||
|
return _window_title_container.size.y
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
custom_minimum_size = _window_title_container.get_minimum_size()
|
||||||
|
|
||||||
|
_options_btn.visible = false
|
||||||
|
|
||||||
|
_title_btn.button_down.connect(
|
||||||
|
func():
|
||||||
|
_is_dragging = true
|
||||||
|
_drag_start_position = get_local_mouse_position()
|
||||||
|
_drag_start_position_global = get_global_mouse_position()
|
||||||
|
)
|
||||||
|
_title_btn.button_up.connect(
|
||||||
|
func():
|
||||||
|
_is_dragging = false
|
||||||
|
)
|
||||||
|
_resize_btn.button_down.connect(
|
||||||
|
func():
|
||||||
|
_is_resizing = true
|
||||||
|
_resize_start_position = _resize_btn.get_local_mouse_position()
|
||||||
|
)
|
||||||
|
_resize_btn.button_up.connect(
|
||||||
|
func():
|
||||||
|
_is_resizing = false
|
||||||
|
)
|
||||||
|
_close_btn.pressed.connect(
|
||||||
|
func():
|
||||||
|
window_closed.emit()
|
||||||
|
if queue_free_on_close:
|
||||||
|
queue_free()
|
||||||
|
else:
|
||||||
|
hide()
|
||||||
|
)
|
||||||
|
|
||||||
|
_title_btn.button.gui_input.connect(
|
||||||
|
func(e):
|
||||||
|
if e is InputEventMouseButton and !e.pressed:
|
||||||
|
if e.button_index != MOUSE_BUTTON_NONE:
|
||||||
|
if (get_global_mouse_position() - _drag_start_position_global).length_squared() < 4:
|
||||||
|
title_btn_clicked.emit()
|
||||||
|
)
|
||||||
|
visibility_changed.connect(
|
||||||
|
func():
|
||||||
|
if is_visible_in_tree() and flicker:
|
||||||
|
$Border.hey_i_am_here()
|
||||||
|
)
|
||||||
|
|
||||||
|
if flicker:
|
||||||
|
$Border.hey_i_am_here()
|
||||||
|
|
||||||
|
_pop_btn.pressed.connect(switch_to_os_window)
|
||||||
|
|
||||||
|
if _container.get_child_count() > 0:
|
||||||
|
_content = _container.get_child(0)
|
||||||
|
|
||||||
|
if get_parent().has_method("get_enable_os_popup_btns"):
|
||||||
|
_pop_btn.visible = get_parent().get_enable_os_popup_btns()
|
||||||
|
|
||||||
|
# feature: foldable window
|
||||||
|
title_btn_clicked.connect(
|
||||||
|
func():
|
||||||
|
if _folded:
|
||||||
|
_target_size = _size_before_folded
|
||||||
|
else:
|
||||||
|
if !_size_animation:
|
||||||
|
_size_before_folded = size
|
||||||
|
_target_size = _window_title_container.size
|
||||||
|
_size_animation = true
|
||||||
|
_folded = !_folded
|
||||||
|
_resize_btn.visible = !_folded
|
||||||
|
)
|
||||||
|
|
||||||
|
func _input(e):
|
||||||
|
#release focus when you click outside of the window
|
||||||
|
if is_visible:
|
||||||
|
if e is InputEventMouseButton and e.pressed:
|
||||||
|
if !get_global_rect().has_point(get_global_mouse_position()):
|
||||||
|
var f = get_viewport().gui_get_focus_owner()
|
||||||
|
if f and is_ancestor_of(f):
|
||||||
|
f.release_focus()
|
||||||
|
if e is InputEventKey and e.keycode == KEY_ESCAPE and e.pressed and get_global_rect().has_point(get_global_mouse_position()):
|
||||||
|
window_closed.emit()
|
||||||
|
if queue_free_on_close:
|
||||||
|
queue_free()
|
||||||
|
else:
|
||||||
|
hide()
|
||||||
|
|
||||||
|
func _process(delta: float) -> void:
|
||||||
|
if !no_move and _is_dragging:
|
||||||
|
var tp := position + get_local_mouse_position() - _drag_start_position
|
||||||
|
position = interp(position, tp, transform_interp_speed, delta)
|
||||||
|
elif !no_resize and _is_resizing:
|
||||||
|
var ts := size + _resize_btn.get_local_mouse_position() - _resize_start_position
|
||||||
|
ts.x = min(ts.x, get_viewport_rect().size.x)
|
||||||
|
ts.y = min(ts.y, get_viewport_rect().size.y)
|
||||||
|
if !no_resize_x:
|
||||||
|
size.x = interp(size.x, ts.x, transform_interp_speed, delta)
|
||||||
|
if !no_resize_y:
|
||||||
|
size.y = interp(size.y, ts.y, transform_interp_speed, delta)
|
||||||
|
elif !no_snap:
|
||||||
|
var window_rect := get_rect()
|
||||||
|
var screen_rect := get_viewport_rect()
|
||||||
|
var target_position := window_rect.position
|
||||||
|
var target_size := window_rect.size.clamp(Vector2.ZERO, screen_rect.size)
|
||||||
|
if window_rect.position.y < 0:
|
||||||
|
target_position.y = 0
|
||||||
|
if window_rect.end.y > screen_rect.end.y:
|
||||||
|
target_position.y = screen_rect.end.y - window_rect.size.y
|
||||||
|
if window_rect.end.y > screen_rect.end.y + window_rect.size.y / 2:
|
||||||
|
target_position.y = screen_rect.end.y - get_title_bar_height()
|
||||||
|
if window_rect.position.x < 0:
|
||||||
|
target_position.x = 0
|
||||||
|
if window_rect.end.x > screen_rect.end.x:
|
||||||
|
target_position.x = screen_rect.end.x - window_rect.size.x
|
||||||
|
var current_position = window_rect.position
|
||||||
|
current_position = interp(current_position, target_position, bounds_interp_speed, delta)
|
||||||
|
size = interp(size, target_size, bounds_interp_speed, delta)
|
||||||
|
position = current_position
|
||||||
|
if _size_animation:
|
||||||
|
if _target_size.is_equal_approx(size):
|
||||||
|
_size_animation = false
|
||||||
|
size = interp(size, _target_size, anim_interp_speed, delta)
|
||||||
|
|
||||||
|
# Framerate-independent interpolation.
|
||||||
|
func interp(from, to, lambda: float, delta: float):
|
||||||
|
return lerp(from, to, 1.0 - exp(-lambda * delta))
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://ctfiphl1luka1
|
||||||
@ -0,0 +1,196 @@
|
|||||||
|
[gd_scene load_steps=19 format=3 uid="uid://s88loppa6gja"]
|
||||||
|
|
||||||
|
[ext_resource type="Material" uid="uid://dyipeqsa8lcpc" path="res://addons/panku_console/common/lynx_window2/lynx_window_shader_material.tres" id="1_tvp6i"]
|
||||||
|
[ext_resource type="Script" path="res://addons/panku_console/common/lynx_window2/lynx_window_2.gd" id="2_1ul5o"]
|
||||||
|
[ext_resource type="Theme" uid="uid://bk18yfu0d77wk" path="res://addons/panku_console/res/panku_console_theme.tres" id="2_3fhqk"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dosm26riekruh" path="res://addons/panku_console/res/icons2/menu.svg" id="4_4dlyn"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://drn5t13m088fb" path="res://addons/panku_console/common/panku_button.tscn" id="4_dnesi"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://gav3m4qtvgje" path="res://addons/panku_console/res/icons2/pop-out-svgrepo-com.svg" id="4_im81u"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://8g5afcuanbl6" path="res://addons/panku_console/res/icons2/close.svg" id="5_l4qpm"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dvr12fl5prm78" path="res://addons/panku_console/res/effect/square_shadow.png" id="6_mfp1h"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://ciu5jiw4xmkq0" path="res://addons/panku_console/res/icons2/resize-svgrepo-com.svg" id="7_duwqn"]
|
||||||
|
[ext_resource type="Script" path="res://addons/panku_console/common/lynx_window2/border.gd" id="8_gj3ji"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_hv45g"]
|
||||||
|
draw_center = false
|
||||||
|
border_width_left = 1
|
||||||
|
border_width_top = 1
|
||||||
|
border_width_right = 1
|
||||||
|
border_width_bottom = 1
|
||||||
|
border_color = Color(1, 1, 1, 0.25098)
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_6i67d"]
|
||||||
|
content_margin_left = 8.0
|
||||||
|
content_margin_top = 8.0
|
||||||
|
content_margin_right = 8.0
|
||||||
|
content_margin_bottom = 8.0
|
||||||
|
draw_center = false
|
||||||
|
border_width_left = 1
|
||||||
|
border_width_right = 1
|
||||||
|
border_width_bottom = 1
|
||||||
|
border_color = Color(1, 1, 1, 0.25098)
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_lct0k"]
|
||||||
|
draw_center = false
|
||||||
|
shadow_color = Color(0, 0, 0, 0.0627451)
|
||||||
|
shadow_size = 16
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_5muk4"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_r0x7y"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_p7tml"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_p3y6j"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_uldta"]
|
||||||
|
draw_center = false
|
||||||
|
border_width_left = 4
|
||||||
|
border_width_top = 4
|
||||||
|
border_width_right = 4
|
||||||
|
border_width_bottom = 4
|
||||||
|
border_color = Color(1, 1, 1, 1)
|
||||||
|
|
||||||
|
[node name="LynxWindow2" type="ColorRect" node_paths=PackedStringArray("_window_title_container", "_title_btn", "_close_btn", "_options_btn", "_resize_btn", "_shadow_focus", "_shadow", "_container", "_pop_btn")]
|
||||||
|
material = ExtResource("1_tvp6i")
|
||||||
|
clip_contents = true
|
||||||
|
offset_right = 413.0
|
||||||
|
offset_bottom = 305.0
|
||||||
|
theme = ExtResource("2_3fhqk")
|
||||||
|
script = ExtResource("2_1ul5o")
|
||||||
|
_window_title_container = NodePath("VBoxContainer/Up")
|
||||||
|
_title_btn = NodePath("VBoxContainer/Up/TitleButton")
|
||||||
|
_close_btn = NodePath("VBoxContainer/Up/CloseButton")
|
||||||
|
_options_btn = NodePath("VBoxContainer/Up/MenuButton")
|
||||||
|
_resize_btn = NodePath("Button")
|
||||||
|
_shadow_focus = NodePath("Shadow2")
|
||||||
|
_shadow = NodePath("Shadow")
|
||||||
|
_container = NodePath("VBoxContainer/Down")
|
||||||
|
_pop_btn = NodePath("VBoxContainer/Up/PopupButton")
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
theme_override_constants/separation = 0
|
||||||
|
|
||||||
|
[node name="Up" type="HBoxContainer" parent="VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_constants/separation = 0
|
||||||
|
|
||||||
|
[node name="TitleButton" parent="VBoxContainer/Up" instance=ExtResource("4_dnesi")]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_hv45g")
|
||||||
|
|
||||||
|
[node name="TextureRect" parent="VBoxContainer/Up/TitleButton/HBoxContainer" index="0"]
|
||||||
|
texture = null
|
||||||
|
|
||||||
|
[node name="Label" parent="VBoxContainer/Up/TitleButton/HBoxContainer" index="1"]
|
||||||
|
text = "Window Title"
|
||||||
|
|
||||||
|
[node name="PopupButton" parent="VBoxContainer/Up" instance=ExtResource("4_dnesi")]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_hv45g")
|
||||||
|
|
||||||
|
[node name="TextureRect" parent="VBoxContainer/Up/PopupButton/HBoxContainer" index="0"]
|
||||||
|
texture = ExtResource("4_im81u")
|
||||||
|
|
||||||
|
[node name="Label" parent="VBoxContainer/Up/PopupButton/HBoxContainer" index="1"]
|
||||||
|
visible = false
|
||||||
|
|
||||||
|
[node name="MenuButton" parent="VBoxContainer/Up" instance=ExtResource("4_dnesi")]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_hv45g")
|
||||||
|
|
||||||
|
[node name="TextureRect" parent="VBoxContainer/Up/MenuButton/HBoxContainer" index="0"]
|
||||||
|
texture = ExtResource("4_4dlyn")
|
||||||
|
|
||||||
|
[node name="Label" parent="VBoxContainer/Up/MenuButton/HBoxContainer" index="1"]
|
||||||
|
visible = false
|
||||||
|
|
||||||
|
[node name="CloseButton" parent="VBoxContainer/Up" instance=ExtResource("4_dnesi")]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_hv45g")
|
||||||
|
|
||||||
|
[node name="TextureRect" parent="VBoxContainer/Up/CloseButton/HBoxContainer" index="0"]
|
||||||
|
texture = ExtResource("5_l4qpm")
|
||||||
|
|
||||||
|
[node name="Label" parent="VBoxContainer/Up/CloseButton/HBoxContainer" index="1"]
|
||||||
|
visible = false
|
||||||
|
|
||||||
|
[node name="Down" type="Panel" parent="VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 3
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_6i67d")
|
||||||
|
|
||||||
|
[node name="Shadow" type="NinePatchRect" parent="."]
|
||||||
|
self_modulate = Color(1, 1, 1, 0.501961)
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = -64.0
|
||||||
|
offset_top = -79.0
|
||||||
|
offset_right = 63.0
|
||||||
|
offset_bottom = 47.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
texture = ExtResource("6_mfp1h")
|
||||||
|
draw_center = false
|
||||||
|
region_rect = Rect2(0, 0, 512, 512)
|
||||||
|
patch_margin_left = 64
|
||||||
|
patch_margin_top = 80
|
||||||
|
patch_margin_right = 64
|
||||||
|
patch_margin_bottom = 48
|
||||||
|
|
||||||
|
[node name="Shadow2" type="Panel" parent="."]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
mouse_filter = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_lct0k")
|
||||||
|
|
||||||
|
[node name="Button" type="Button" parent="."]
|
||||||
|
self_modulate = Color(1, 1, 1, 0.501961)
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 3
|
||||||
|
anchor_left = 1.0
|
||||||
|
anchor_top = 1.0
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = -12.0
|
||||||
|
offset_top = -12.0
|
||||||
|
grow_horizontal = 0
|
||||||
|
grow_vertical = 0
|
||||||
|
mouse_default_cursor_shape = 12
|
||||||
|
theme_override_styles/normal = SubResource("StyleBoxEmpty_5muk4")
|
||||||
|
theme_override_styles/hover = SubResource("StyleBoxEmpty_r0x7y")
|
||||||
|
theme_override_styles/pressed = SubResource("StyleBoxEmpty_p7tml")
|
||||||
|
theme_override_styles/focus = SubResource("StyleBoxEmpty_p3y6j")
|
||||||
|
icon = ExtResource("7_duwqn")
|
||||||
|
flat = true
|
||||||
|
expand_icon = true
|
||||||
|
|
||||||
|
[node name="Border" type="Panel" parent="."]
|
||||||
|
modulate = Color(1, 1, 1, 0)
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
mouse_filter = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxFlat_uldta")
|
||||||
|
script = ExtResource("8_gj3ji")
|
||||||
|
|
||||||
|
[editable path="VBoxContainer/Up/TitleButton"]
|
||||||
|
[editable path="VBoxContainer/Up/PopupButton"]
|
||||||
|
[editable path="VBoxContainer/Up/MenuButton"]
|
||||||
|
[editable path="VBoxContainer/Up/CloseButton"]
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
[gd_resource type="ShaderMaterial" load_steps=2 format=3 uid="uid://dyipeqsa8lcpc"]
|
||||||
|
|
||||||
|
[ext_resource type="Shader" path="res://addons/panku_console/res/shader/simple_fast_blur.gdshader" id="1_3h55m"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
shader = ExtResource("1_3h55m")
|
||||||
|
shader_parameter/lod = 4.0
|
||||||
|
shader_parameter/modulate = Color(0, 0, 0, 0.12549)
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
#A simple control node managing its child windows
|
||||||
|
class_name PankuLynxWindowsManager extends Control
|
||||||
|
|
||||||
|
const CFG_ENABLE_OS_WINDOW = "enable_os_window"
|
||||||
|
const CFG_OS_WINDOW_BGCOLOR = "os_window_bg_color"
|
||||||
|
|
||||||
|
@onready var console:PankuConsole = get_node(PankuConsole.SingletonPath)
|
||||||
|
|
||||||
|
var os_popup_btn_enabled:bool
|
||||||
|
var os_window_bg_color:Color
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
load_data()
|
||||||
|
|
||||||
|
func _input(e):
|
||||||
|
if e is InputEventMouseButton and e.pressed:
|
||||||
|
var flag = true
|
||||||
|
#traverse child windows in reverse order, use double shadow to highlight current active window.
|
||||||
|
for i in range(get_child_count() - 1, -1, -1):
|
||||||
|
var w:Control = get_child(i)
|
||||||
|
if w.visible and w.get_global_rect().has_point(get_global_mouse_position()):
|
||||||
|
var forefront = get_child(get_child_count() - 1)
|
||||||
|
if forefront.has_method("highlight"): forefront.highlight(false)
|
||||||
|
w.move_to_front()
|
||||||
|
forefront = get_child(get_child_count() - 1)
|
||||||
|
if forefront.has_method("highlight"): forefront.highlight(true)
|
||||||
|
flag = false
|
||||||
|
break
|
||||||
|
if flag and get_child_count() > 0:
|
||||||
|
var forefront = get_child(get_child_count() - 1)
|
||||||
|
if forefront.has_method("highlight"): forefront.highlight(false)
|
||||||
|
|
||||||
|
func create_window(content:Control) -> PankuLynxWindow:
|
||||||
|
var new_window:PankuLynxWindow = preload("lynx_window_2.tscn").instantiate()
|
||||||
|
content.anchors_preset = Control.PRESET_FULL_RECT
|
||||||
|
new_window.set_content(content)
|
||||||
|
add_child(new_window)
|
||||||
|
new_window.show_window()
|
||||||
|
return new_window
|
||||||
|
|
||||||
|
func enable_os_popup_btns(b:bool):
|
||||||
|
#note that this may affect your project
|
||||||
|
get_viewport().gui_embed_subwindows = !b
|
||||||
|
os_popup_btn_enabled = b
|
||||||
|
for w in get_children():
|
||||||
|
#maybe there's a better way to get node type
|
||||||
|
if !w.has_method("switch_to_os_window"):
|
||||||
|
continue
|
||||||
|
w._pop_btn.visible = b
|
||||||
|
|
||||||
|
func get_enable_os_popup_btns() -> bool:
|
||||||
|
return os_popup_btn_enabled
|
||||||
|
|
||||||
|
func set_os_window_bg_color(c:Color):
|
||||||
|
os_window_bg_color = c
|
||||||
|
for w in get_children():
|
||||||
|
#maybe there's a better way to get node type
|
||||||
|
if !w.has_method("switch_to_os_window"):
|
||||||
|
continue
|
||||||
|
if w._os_window != null:
|
||||||
|
w._os_window.get_child(0).color = c
|
||||||
|
|
||||||
|
func get_os_window_bg_color() -> Color:
|
||||||
|
return os_window_bg_color
|
||||||
|
|
||||||
|
func save_data():
|
||||||
|
var cfg = PankuConfig.get_config()
|
||||||
|
cfg[CFG_ENABLE_OS_WINDOW] = os_popup_btn_enabled
|
||||||
|
cfg[CFG_OS_WINDOW_BGCOLOR] = os_window_bg_color
|
||||||
|
PankuConfig.set_config(cfg)
|
||||||
|
|
||||||
|
func load_data():
|
||||||
|
var cfg = PankuConfig.get_config()
|
||||||
|
enable_os_popup_btns(cfg.get(CFG_ENABLE_OS_WINDOW, false))
|
||||||
|
set_os_window_bg_color(cfg.get(CFG_OS_WINDOW_BGCOLOR, Color("#2b2e32")))
|
||||||
|
|
||||||
|
func _notification(what):
|
||||||
|
#quit event
|
||||||
|
if what == NOTIFICATION_WM_CLOSE_REQUEST:
|
||||||
|
save_data()
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://ciferd4gytj41
|
||||||
54
source/addons/panku_console/common/module_manager.gd
Normal file
54
source/addons/panku_console/common/module_manager.gd
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
class_name PankuModuleManager
|
||||||
|
|
||||||
|
var _modules:Array[PankuModule]
|
||||||
|
var _modules_table:Dictionary
|
||||||
|
var _core:PankuConsole
|
||||||
|
|
||||||
|
func init_manager(_core:PankuConsole, _modules:Array[PankuModule]):
|
||||||
|
self._modules = _modules
|
||||||
|
self._core = _core
|
||||||
|
load_modules()
|
||||||
|
|
||||||
|
func load_modules():
|
||||||
|
|
||||||
|
# The extra tree structure is purely used for avoiding using RefCounted which may cause uncessary leaked instance warnings.
|
||||||
|
var manager_node:Node = Node.new()
|
||||||
|
manager_node.name = "_Modules_"
|
||||||
|
_core.add_child(manager_node)
|
||||||
|
|
||||||
|
for _m in _modules:
|
||||||
|
var module:PankuModule = _m
|
||||||
|
_modules_table[module.get_module_name()] = module
|
||||||
|
|
||||||
|
module.name = module.get_module_name()
|
||||||
|
manager_node.add_child(module)
|
||||||
|
|
||||||
|
for _m in _modules:
|
||||||
|
var module:PankuModule = _m
|
||||||
|
module.core = _core
|
||||||
|
module._init_module()
|
||||||
|
#print("[info] %s module loaded!" % module.get_module_name())
|
||||||
|
|
||||||
|
func update_modules(delta:float):
|
||||||
|
for _m in _modules:
|
||||||
|
var module:PankuModule = _m
|
||||||
|
module.update_module(delta)
|
||||||
|
|
||||||
|
func get_module(module_name:String):
|
||||||
|
return _modules_table[module_name]
|
||||||
|
|
||||||
|
func has_module(module_name:String):
|
||||||
|
return _modules_table.has(module_name)
|
||||||
|
|
||||||
|
func get_module_option_objects():
|
||||||
|
var objects = []
|
||||||
|
for _m in _modules:
|
||||||
|
var module:PankuModule = _m
|
||||||
|
if module._opt != null:
|
||||||
|
objects.append(module._opt)
|
||||||
|
return objects
|
||||||
|
|
||||||
|
func quit_modules():
|
||||||
|
for _m in _modules:
|
||||||
|
var module:PankuModule = _m
|
||||||
|
module.quit_module()
|
||||||
1
source/addons/panku_console/common/module_manager.gd.uid
Normal file
1
source/addons/panku_console/common/module_manager.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://ciurr4mc7r71x
|
||||||
11
source/addons/panku_console/common/module_options.gd
Normal file
11
source/addons/panku_console/common/module_options.gd
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
class_name ModuleOptions extends Resource
|
||||||
|
|
||||||
|
var _module:PankuModule
|
||||||
|
|
||||||
|
var _loaded := false
|
||||||
|
|
||||||
|
#FIXME: Tricky part of saving data, needs to be reworked
|
||||||
|
func update_setting(key: String, value: Variant):
|
||||||
|
self.set(key, value)
|
||||||
|
if _loaded and _module:
|
||||||
|
_module.save_module_data(key, value)
|
||||||
1
source/addons/panku_console/common/module_options.gd.uid
Normal file
1
source/addons/panku_console/common/module_options.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://c43wmdfwptw3v
|
||||||
39
source/addons/panku_console/common/panku_button.gd
Normal file
39
source/addons/panku_console/common/panku_button.gd
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
class_name PankuButton extends Control
|
||||||
|
|
||||||
|
signal pressed
|
||||||
|
signal button_down
|
||||||
|
signal button_up
|
||||||
|
|
||||||
|
@export
|
||||||
|
var button:Button
|
||||||
|
|
||||||
|
@export
|
||||||
|
var trect:TextureRect
|
||||||
|
|
||||||
|
@export
|
||||||
|
var label:Label
|
||||||
|
|
||||||
|
var icon:
|
||||||
|
set(v):
|
||||||
|
trect.texture = v
|
||||||
|
get:
|
||||||
|
return trect.texture
|
||||||
|
|
||||||
|
var text:
|
||||||
|
set(v):
|
||||||
|
label.text = v
|
||||||
|
get:
|
||||||
|
return label.text
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
|
||||||
|
button.pressed.connect(
|
||||||
|
func():
|
||||||
|
pressed.emit()
|
||||||
|
)
|
||||||
|
button.button_down.connect(
|
||||||
|
func(): button_down.emit()
|
||||||
|
)
|
||||||
|
button.button_up.connect(
|
||||||
|
func(): button_up.emit()
|
||||||
|
)
|
||||||
1
source/addons/panku_console/common/panku_button.gd.uid
Normal file
1
source/addons/panku_console/common/panku_button.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://0ydmyeffilu7
|
||||||
42
source/addons/panku_console/common/panku_button.tscn
Normal file
42
source/addons/panku_console/common/panku_button.tscn
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
[gd_scene load_steps=5 format=3 uid="uid://drn5t13m088fb"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/panku_console/common/panku_button.gd" id="1_7kf5f"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://dchvk7qgfe37m" path="res://addons/panku_console/res/icons2/fold-svgrepo-com.svg" id="2_su653"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_v3kpx"]
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_cwnaw"]
|
||||||
|
content_margin_top = 4.0
|
||||||
|
content_margin_bottom = 4.0
|
||||||
|
|
||||||
|
[node name="PankuButton" type="PanelContainer" node_paths=PackedStringArray("button", "trect", "label")]
|
||||||
|
editor_description = "Godot's Button can't handle scaling icons properly as descripted in https://github.com/godotengine/godot-proposals/issues/660, so I have to make a new one."
|
||||||
|
self_modulate = Color(1, 1, 1, 0)
|
||||||
|
offset_right = 112.0
|
||||||
|
offset_bottom = 31.0
|
||||||
|
mouse_filter = 2
|
||||||
|
theme_override_styles/panel = SubResource("StyleBoxEmpty_v3kpx")
|
||||||
|
script = ExtResource("1_7kf5f")
|
||||||
|
button = NodePath("Button")
|
||||||
|
trect = NodePath("HBoxContainer/TextureRect")
|
||||||
|
label = NodePath("HBoxContainer/Label")
|
||||||
|
|
||||||
|
[node name="Button" type="Button" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
mouse_filter = 2
|
||||||
|
theme_override_constants/separation = 0
|
||||||
|
|
||||||
|
[node name="TextureRect" type="TextureRect" parent="HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
mouse_filter = 2
|
||||||
|
texture = ExtResource("2_su653")
|
||||||
|
expand_mode = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_vertical = 1
|
||||||
|
theme_override_styles/normal = SubResource("StyleBoxEmpty_cwnaw")
|
||||||
|
vertical_alignment = 1
|
||||||
101
source/addons/panku_console/common/panku_module.gd
Normal file
101
source/addons/panku_console/common/panku_module.gd
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
class_name PankuModule extends Node
|
||||||
|
# extends Node: A hacky way to avoid cyclic RefCounted verbose warnings which is uncessary to worry about.
|
||||||
|
|
||||||
|
var core:PankuConsole
|
||||||
|
|
||||||
|
var _env:RefCounted = null
|
||||||
|
var _opt:ModuleOptions = null
|
||||||
|
|
||||||
|
# dir name of the module
|
||||||
|
func get_module_name() -> String:
|
||||||
|
return get_script().resource_path.get_base_dir().get_file()
|
||||||
|
|
||||||
|
# called when the module is loaded
|
||||||
|
func init_module():
|
||||||
|
pass
|
||||||
|
|
||||||
|
# called when the module is unloaded (quit program)
|
||||||
|
func quit_module():
|
||||||
|
if _opt:
|
||||||
|
_opt._loaded = false
|
||||||
|
|
||||||
|
# called at the start of each physics frame
|
||||||
|
func update_module(delta:float):
|
||||||
|
pass
|
||||||
|
|
||||||
|
func save_module_data(key:String, value:Variant):
|
||||||
|
var cfg:Dictionary = PankuConfig.get_config()
|
||||||
|
var module_name:String = get_module_name()
|
||||||
|
if !cfg.has(module_name):
|
||||||
|
cfg[module_name] = {}
|
||||||
|
cfg[module_name][key] = value
|
||||||
|
PankuConfig.set_config(cfg)
|
||||||
|
|
||||||
|
func load_module_data(key:String, default_value:Variant = null) -> Variant:
|
||||||
|
var cfg:Dictionary = PankuConfig.get_config()
|
||||||
|
var module_name:String = get_module_name()
|
||||||
|
var module_data = cfg.get(module_name, {})
|
||||||
|
return module_data.get(key, default_value)
|
||||||
|
|
||||||
|
func has_module_data(key:String) -> bool:
|
||||||
|
var cfg:Dictionary = PankuConfig.get_config()
|
||||||
|
var module_name:String = get_module_name()
|
||||||
|
var module_data = cfg.get(module_name, {})
|
||||||
|
return module_data.has(key)
|
||||||
|
|
||||||
|
func load_window_data(window:PankuLynxWindow):
|
||||||
|
window.position = load_module_data("window_position", window.get_layout_position([
|
||||||
|
Control.PRESET_TOP_LEFT,
|
||||||
|
Control.PRESET_CENTER_TOP,
|
||||||
|
Control.PRESET_TOP_RIGHT,
|
||||||
|
Control.PRESET_CENTER_LEFT,
|
||||||
|
Control.PRESET_CENTER,
|
||||||
|
Control.PRESET_CENTER_RIGHT,
|
||||||
|
Control.PRESET_BOTTOM_LEFT,
|
||||||
|
Control.PRESET_CENTER_BOTTOM,
|
||||||
|
Control.PRESET_BOTTOM_RIGHT,
|
||||||
|
][randi()%9]))
|
||||||
|
window.size = load_module_data("window_size", window.get_normal_window_size())
|
||||||
|
window.set_window_visibility(load_module_data("window_visibility", false))
|
||||||
|
|
||||||
|
func save_window_data(window:PankuLynxWindow):
|
||||||
|
_save_window_geometry(window)
|
||||||
|
save_module_data("window_visibility", window.visible)
|
||||||
|
|
||||||
|
|
||||||
|
func _save_window_geometry(window:PankuLynxWindow):
|
||||||
|
save_module_data("window_position", window.position)
|
||||||
|
save_module_data("window_size", window.get_normal_window_size())
|
||||||
|
|
||||||
|
|
||||||
|
# Add hook to window to auto save its geometry on close.
|
||||||
|
func add_auto_save_hook(window: PankuLynxWindow) -> void:
|
||||||
|
# Here some global settings check can be implemented,
|
||||||
|
# if we decide to make "save on close" feature optional
|
||||||
|
window.window_closed.connect(_save_window_geometry.bind(window))
|
||||||
|
|
||||||
|
|
||||||
|
func get_module_env() -> RefCounted:
|
||||||
|
return _env
|
||||||
|
|
||||||
|
func get_module_opt() -> ModuleOptions:
|
||||||
|
return _opt
|
||||||
|
|
||||||
|
func _init_module():
|
||||||
|
var module_script_dir:String = get_script().resource_path.get_base_dir()
|
||||||
|
var env_script_path = module_script_dir + "/env.gd"
|
||||||
|
var opt_script_path = module_script_dir + "/opt.gd"
|
||||||
|
|
||||||
|
if FileAccess.file_exists(env_script_path):
|
||||||
|
_env = load(env_script_path).new()
|
||||||
|
_env._module = self
|
||||||
|
core.gd_exprenv.register_env(get_module_name(), _env)
|
||||||
|
|
||||||
|
if FileAccess.file_exists(opt_script_path):
|
||||||
|
#print(opt_script_path)
|
||||||
|
_opt = load(opt_script_path).new() as ModuleOptions
|
||||||
|
_opt._module = self
|
||||||
|
|
||||||
|
init_module()
|
||||||
|
if _opt:
|
||||||
|
_opt._loaded = true
|
||||||
1
source/addons/panku_console/common/panku_module.gd.uid
Normal file
1
source/addons/panku_console/common/panku_module.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://d21arokusrmjd
|
||||||
23
source/addons/panku_console/common/repl_base_instance.gd
Normal file
23
source/addons/panku_console/common/repl_base_instance.gd
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
var _core:PankuConsole
|
||||||
|
|
||||||
|
const _HELP_help := "List all environment variables."
|
||||||
|
var help:String:
|
||||||
|
get:
|
||||||
|
var result = ["Registered objects:\n"]
|
||||||
|
var colors = ["#7c3f58", "#eb6b6f", "#f9a875", "#fff6d3"]
|
||||||
|
var i = 0
|
||||||
|
for k in _core.gd_exprenv._envs:
|
||||||
|
var c = colors[i%4]
|
||||||
|
i = i + 1
|
||||||
|
result.push_back("[b][color=%s]%s[/color][/b] "%[c, k])
|
||||||
|
result.push_back("\n")
|
||||||
|
result.push_back("You can type [b]helpe(object)[/b] to get more information.")
|
||||||
|
return "".join(PackedStringArray(result))
|
||||||
|
|
||||||
|
const _HELP_helpe := "Provide detailed information about one specific environment variable."
|
||||||
|
func helpe(obj:Object) -> String:
|
||||||
|
if !obj:
|
||||||
|
return "Invalid!"
|
||||||
|
if !obj.get_script():
|
||||||
|
return "It has no attached script!"
|
||||||
|
return PankuGDExprEnv.generate_help_text_from_script(obj.get_script())
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://cw0ur3eb0henf
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
extends PanelContainer
|
||||||
|
|
||||||
|
@export var clip_container:Control
|
||||||
|
|
||||||
|
@export var scrollbar:VScrollBar
|
||||||
|
|
||||||
|
@export var follow_content:bool = true
|
||||||
|
|
||||||
|
@onready var content:Control = clip_container.get_child(0)
|
||||||
|
|
||||||
|
var scroll_progress:float = 0.0
|
||||||
|
var prev_content_size_y:float = 0.0
|
||||||
|
|
||||||
|
func init_progressbar() -> void:
|
||||||
|
scrollbar.min_value = 0.0
|
||||||
|
scrollbar.allow_greater = true
|
||||||
|
scrollbar.allow_lesser = true
|
||||||
|
scrollbar.value = 0.0
|
||||||
|
|
||||||
|
func _gui_input(event: InputEvent) -> void:
|
||||||
|
if event is InputEventMouseButton and event.is_pressed():
|
||||||
|
var step:float = clip_container.size.y / 8.0
|
||||||
|
if event.button_index == MOUSE_BUTTON_WHEEL_UP:
|
||||||
|
scrollbar.value -= step
|
||||||
|
if event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
|
||||||
|
scrollbar.value += step
|
||||||
|
|
||||||
|
func _process(delta: float) -> void:
|
||||||
|
content.size = Vector2(clip_container.size.x, 0)
|
||||||
|
content.position = Vector2.ZERO
|
||||||
|
scrollbar.max_value = content.size.y
|
||||||
|
var scrollbar_value_max = max(0, scrollbar.max_value - clip_container.size.y)
|
||||||
|
scrollbar.value = lerp(scrollbar.value, clampf(scrollbar.value, 0.0, scrollbar_value_max), 0.2)
|
||||||
|
scrollbar.page = clip_container.size.y
|
||||||
|
scrollbar.visible = content.size.y > clip_container.size.y
|
||||||
|
|
||||||
|
scroll_progress = lerp(scroll_progress, scrollbar.value, 0.2)
|
||||||
|
content.position.y = - scroll_progress
|
||||||
|
|
||||||
|
if !follow_content: return
|
||||||
|
if prev_content_size_y != content.size.y:
|
||||||
|
var should_follow:bool = (scrollbar.value + scrollbar.page) / prev_content_size_y > 0.99
|
||||||
|
prev_content_size_y = content.size.y
|
||||||
|
if should_follow:
|
||||||
|
scrollbar.value = scrollbar.max_value - scrollbar.page
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
init_progressbar()
|
||||||
@ -0,0 +1 @@
|
|||||||
|
uid://rd44n33h004h
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
[gd_scene load_steps=3 format=3 uid="uid://dyq4rjkkjs55d"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://addons/panku_console/common/smooth_scroll/smooth_scroll.gd" id="1_ma8ku"]
|
||||||
|
[ext_resource type="Theme" uid="uid://bk18yfu0d77wk" path="res://addons/panku_console/res/panku_console_theme.tres" id="1_pa7xs"]
|
||||||
|
|
||||||
|
[node name="SmoothScrollContainer" type="PanelContainer" node_paths=PackedStringArray("clip_container", "scrollbar")]
|
||||||
|
self_modulate = Color(1, 1, 1, 0)
|
||||||
|
clip_contents = true
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
theme = ExtResource("1_pa7xs")
|
||||||
|
script = ExtResource("1_ma8ku")
|
||||||
|
clip_container = NodePath("HBoxContainer/Control")
|
||||||
|
scrollbar = NodePath("HBoxContainer/VScrollBar")
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="."]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Control" type="Control" parent="HBoxContainer"]
|
||||||
|
clip_contents = true
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
|
||||||
|
[node name="VScrollBar" type="VScrollBar" parent="HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
page = 20.0
|
||||||
|
value = 80.0
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user