Merge pull request #87625 from YuriSizov/editor-lightweight-script-previews
Generate script resource preview without parsing
This commit is contained in:
commit
1774c17b64
5 changed files with 55 additions and 10 deletions
|
@ -168,6 +168,18 @@ ScriptLanguage *ScriptServer::get_language(int p_idx) {
|
||||||
return _languages[p_idx];
|
return _languages[p_idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScriptLanguage *ScriptServer::get_language_for_extension(const String &p_extension) {
|
||||||
|
MutexLock lock(languages_mutex);
|
||||||
|
|
||||||
|
for (int i = 0; i < _language_count; i++) {
|
||||||
|
if (_languages[i] && _languages[i]->get_extension() == p_extension) {
|
||||||
|
return _languages[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
Error ScriptServer::register_language(ScriptLanguage *p_language) {
|
Error ScriptServer::register_language(ScriptLanguage *p_language) {
|
||||||
MutexLock lock(languages_mutex);
|
MutexLock lock(languages_mutex);
|
||||||
ERR_FAIL_NULL_V(p_language, ERR_INVALID_PARAMETER);
|
ERR_FAIL_NULL_V(p_language, ERR_INVALID_PARAMETER);
|
||||||
|
|
|
@ -75,6 +75,7 @@ public:
|
||||||
static bool is_scripting_enabled();
|
static bool is_scripting_enabled();
|
||||||
_FORCE_INLINE_ static int get_language_count() { return _language_count; }
|
_FORCE_INLINE_ static int get_language_count() { return _language_count; }
|
||||||
static ScriptLanguage *get_language(int p_idx);
|
static ScriptLanguage *get_language(int p_idx);
|
||||||
|
static ScriptLanguage *get_language_for_extension(const String &p_extension);
|
||||||
static Error register_language(ScriptLanguage *p_language);
|
static Error register_language(ScriptLanguage *p_language);
|
||||||
static Error unregister_language(const ScriptLanguage *p_language);
|
static Error unregister_language(const ScriptLanguage *p_language);
|
||||||
|
|
||||||
|
|
|
@ -129,6 +129,8 @@ void EditorResourcePreview::_preview_ready(const String &p_path, int p_hash, con
|
||||||
void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref<ImageTexture> &r_small_texture, const QueueItem &p_item, const String &cache_base, Dictionary &p_metadata) {
|
void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref<ImageTexture> &r_small_texture, const QueueItem &p_item, const String &cache_base, Dictionary &p_metadata) {
|
||||||
String type;
|
String type;
|
||||||
|
|
||||||
|
uint64_t started_at = OS::get_singleton()->get_ticks_usec();
|
||||||
|
|
||||||
if (p_item.resource.is_valid()) {
|
if (p_item.resource.is_valid()) {
|
||||||
type = p_item.resource->get_class();
|
type = p_item.resource->get_class();
|
||||||
} else {
|
} else {
|
||||||
|
@ -138,6 +140,10 @@ void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref<
|
||||||
if (type.is_empty()) {
|
if (type.is_empty()) {
|
||||||
r_texture = Ref<ImageTexture>();
|
r_texture = Ref<ImageTexture>();
|
||||||
r_small_texture = Ref<ImageTexture>();
|
r_small_texture = Ref<ImageTexture>();
|
||||||
|
|
||||||
|
if (is_print_verbose_enabled()) {
|
||||||
|
print_line(vformat("Generated '%s' preview in %d usec", p_item.path, OS::get_singleton()->get_ticks_usec() - started_at));
|
||||||
|
}
|
||||||
return; //could not guess type
|
return; //could not guess type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,6 +202,10 @@ void EditorResourcePreview::_generate_preview(Ref<ImageTexture> &r_texture, Ref<
|
||||||
_write_preview_cache(f, thumbnail_size, has_small_texture, FileAccess::get_modified_time(p_item.path), FileAccess::get_md5(p_item.path), p_metadata);
|
_write_preview_cache(f, thumbnail_size, has_small_texture, FileAccess::get_modified_time(p_item.path), FileAccess::get_md5(p_item.path), p_metadata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_print_verbose_enabled()) {
|
||||||
|
print_line(vformat("Generated '%s' preview in %d usec", p_item.path, OS::get_singleton()->get_ticks_usec() - started_at));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Dictionary EditorResourcePreview::get_preview_metadata(const String &p_path) const {
|
const Dictionary EditorResourcePreview::get_preview_metadata(const String &p_path) const {
|
||||||
|
|
|
@ -464,6 +464,17 @@ bool EditorScriptPreviewPlugin::handles(const String &p_type) const {
|
||||||
return ClassDB::is_parent_class(p_type, "Script");
|
return ClassDB::is_parent_class(p_type, "Script");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ref<Texture2D> EditorScriptPreviewPlugin::generate_from_path(const String &p_path, const Size2 &p_size, Dictionary &p_metadata) const {
|
||||||
|
Error err;
|
||||||
|
String code = FileAccess::get_file_as_string(p_path, &err);
|
||||||
|
if (err != OK) {
|
||||||
|
return Ref<Texture2D>();
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptLanguage *lang = ScriptServer::get_language_for_extension(p_path.get_extension());
|
||||||
|
return _generate_from_source_code(lang, code, p_size, p_metadata);
|
||||||
|
}
|
||||||
|
|
||||||
Ref<Texture2D> EditorScriptPreviewPlugin::generate(const Ref<Resource> &p_from, const Size2 &p_size, Dictionary &p_metadata) const {
|
Ref<Texture2D> EditorScriptPreviewPlugin::generate(const Ref<Resource> &p_from, const Size2 &p_size, Dictionary &p_metadata) const {
|
||||||
Ref<Script> scr = p_from;
|
Ref<Script> scr = p_from;
|
||||||
if (scr.is_null()) {
|
if (scr.is_null()) {
|
||||||
|
@ -471,18 +482,24 @@ Ref<Texture2D> EditorScriptPreviewPlugin::generate(const Ref<Resource> &p_from,
|
||||||
}
|
}
|
||||||
|
|
||||||
String code = scr->get_source_code().strip_edges();
|
String code = scr->get_source_code().strip_edges();
|
||||||
if (code.is_empty()) {
|
return _generate_from_source_code(scr->get_language(), code, p_size, p_metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<Texture2D> EditorScriptPreviewPlugin::_generate_from_source_code(const ScriptLanguage *p_language, const String &p_source_code, const Size2 &p_size, Dictionary &p_metadata) const {
|
||||||
|
if (p_source_code.is_empty()) {
|
||||||
return Ref<Texture2D>();
|
return Ref<Texture2D>();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> kwors;
|
List<String> kwors;
|
||||||
scr->get_language()->get_reserved_words(&kwors);
|
if (p_language) {
|
||||||
|
p_language->get_reserved_words(&kwors);
|
||||||
|
}
|
||||||
|
|
||||||
HashSet<String> control_flow_keywords;
|
HashSet<String> control_flow_keywords;
|
||||||
HashSet<String> keywords;
|
HashSet<String> keywords;
|
||||||
|
|
||||||
for (const String &E : kwors) {
|
for (const String &E : kwors) {
|
||||||
if (scr->get_language()->is_control_flow_keyword(E)) {
|
if (p_language && p_language->is_control_flow_keyword(E)) {
|
||||||
control_flow_keywords.insert(E);
|
control_flow_keywords.insert(E);
|
||||||
} else {
|
} else {
|
||||||
keywords.insert(E);
|
keywords.insert(E);
|
||||||
|
@ -505,7 +522,7 @@ Ref<Texture2D> EditorScriptPreviewPlugin::generate(const Ref<Resource> &p_from,
|
||||||
if (bg_color.a == 0) {
|
if (bg_color.a == 0) {
|
||||||
bg_color = Color(0, 0, 0, 0);
|
bg_color = Color(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
bg_color.a = MAX(bg_color.a, 0.2); // some background
|
bg_color.a = MAX(bg_color.a, 0.2); // Ensure we have some background, regardless of the text editor setting.
|
||||||
|
|
||||||
img->fill(bg_color);
|
img->fill(bg_color);
|
||||||
|
|
||||||
|
@ -519,14 +536,14 @@ Ref<Texture2D> EditorScriptPreviewPlugin::generate(const Ref<Resource> &p_from,
|
||||||
bool in_keyword = false;
|
bool in_keyword = false;
|
||||||
bool in_comment = false;
|
bool in_comment = false;
|
||||||
bool in_doc_comment = false;
|
bool in_doc_comment = false;
|
||||||
for (int i = 0; i < code.length(); i++) {
|
for (int i = 0; i < p_source_code.length(); i++) {
|
||||||
char32_t c = code[i];
|
char32_t c = p_source_code[i];
|
||||||
if (c > 32) {
|
if (c > 32) {
|
||||||
if (col < thumbnail_size) {
|
if (col < thumbnail_size) {
|
||||||
Color color = text_color;
|
Color color = text_color;
|
||||||
|
|
||||||
if (c == '#') {
|
if (c == '#') {
|
||||||
if (i < code.length() - 1 && code[i + 1] == '#') {
|
if (i < p_source_code.length() - 1 && p_source_code[i + 1] == '#') {
|
||||||
in_doc_comment = true;
|
in_doc_comment = true;
|
||||||
} else {
|
} else {
|
||||||
in_comment = true;
|
in_comment = true;
|
||||||
|
@ -539,17 +556,17 @@ Ref<Texture2D> EditorScriptPreviewPlugin::generate(const Ref<Resource> &p_from,
|
||||||
color = doc_comment_color;
|
color = doc_comment_color;
|
||||||
} else {
|
} else {
|
||||||
if (is_symbol(c)) {
|
if (is_symbol(c)) {
|
||||||
//make symbol a little visible
|
// Make symbol a little visible.
|
||||||
color = symbol_color;
|
color = symbol_color;
|
||||||
in_control_flow_keyword = false;
|
in_control_flow_keyword = false;
|
||||||
in_keyword = false;
|
in_keyword = false;
|
||||||
} else if (!prev_is_text && is_ascii_identifier_char(c)) {
|
} else if (!prev_is_text && is_ascii_identifier_char(c)) {
|
||||||
int pos = i;
|
int pos = i;
|
||||||
|
|
||||||
while (is_ascii_identifier_char(code[pos])) {
|
while (is_ascii_identifier_char(p_source_code[pos])) {
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
String word = code.substr(i, pos - i);
|
String word = p_source_code.substr(i, pos - i);
|
||||||
if (control_flow_keywords.has(word)) {
|
if (control_flow_keywords.has(word)) {
|
||||||
in_control_flow_keyword = true;
|
in_control_flow_keyword = true;
|
||||||
} else if (keywords.has(word)) {
|
} else if (keywords.has(word)) {
|
||||||
|
|
|
@ -34,6 +34,8 @@
|
||||||
#include "core/templates/safe_refcount.h"
|
#include "core/templates/safe_refcount.h"
|
||||||
#include "editor/editor_resource_preview.h"
|
#include "editor/editor_resource_preview.h"
|
||||||
|
|
||||||
|
class ScriptLanguage;
|
||||||
|
|
||||||
void post_process_preview(Ref<Image> p_image);
|
void post_process_preview(Ref<Image> p_image);
|
||||||
|
|
||||||
class EditorTexturePreviewPlugin : public EditorResourcePreviewGenerator {
|
class EditorTexturePreviewPlugin : public EditorResourcePreviewGenerator {
|
||||||
|
@ -112,9 +114,12 @@ public:
|
||||||
class EditorScriptPreviewPlugin : public EditorResourcePreviewGenerator {
|
class EditorScriptPreviewPlugin : public EditorResourcePreviewGenerator {
|
||||||
GDCLASS(EditorScriptPreviewPlugin, EditorResourcePreviewGenerator);
|
GDCLASS(EditorScriptPreviewPlugin, EditorResourcePreviewGenerator);
|
||||||
|
|
||||||
|
Ref<Texture2D> _generate_from_source_code(const ScriptLanguage *p_language, const String &p_source_code, const Size2 &p_size, Dictionary &p_metadata) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual bool handles(const String &p_type) const override;
|
virtual bool handles(const String &p_type) const override;
|
||||||
virtual Ref<Texture2D> generate(const Ref<Resource> &p_from, const Size2 &p_size, Dictionary &p_metadata) const override;
|
virtual Ref<Texture2D> generate(const Ref<Resource> &p_from, const Size2 &p_size, Dictionary &p_metadata) const override;
|
||||||
|
virtual Ref<Texture2D> generate_from_path(const String &p_path, const Size2 &p_size, Dictionary &p_metadata) const override;
|
||||||
|
|
||||||
EditorScriptPreviewPlugin();
|
EditorScriptPreviewPlugin();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue