Repository navigation
Add no-copy versions of TextServer::shaped_text_{get_glyphs,sort_logical,get_ellipsis_glyphs} for gdextensions to use. - #124561
Draft
BenLubar wants to merge 1 commit into
Conversation
BenLubar
force-pushed
the
text-server-gdextension-nocopy-get-glyphs
branch
3 times, most recently
from
October 16, 2026 21:33
eb39c53 to
7d43edc
Compare
bruvzg
reviewed
Oct 19, 2026
bruvzg
left a comment
Member
There was a problem hiding this comment.
I do not think it should be exposed in the main API, but it's probably OK to do it in the text server code (I only did one method as example):
diff --git a/servers/text/text_server.h b/servers/text/text_server.h
index 311b2d2243..d4e963cbcb 100644
--- a/servers/text/text_server.h
+++ b/servers/text/text_server.h
@@ -537,8 +537,9 @@ public:
bool shaped_text_has_visible_chars(const RID &p_shaped) const;
virtual const Glyph *shaped_text_get_glyphs(const RID &p_shaped) const = 0;
TypedArray<Dictionary> _shaped_text_get_glyphs_wrapper(const RID &p_shaped) const;
+ GDExtensionPtr<const Glyph> _shaped_text_get_glyphs_gde_wrapper(const RID &p_shaped) const;
virtual const Glyph *shaped_text_sort_logical(const RID &p_shaped) = 0;
TypedArray<Dictionary> _shaped_text_sort_logical_wrapper(const RID &p_shaped);
virtual int64_t shaped_text_get_glyph_count(const RID &p_shaped) const = 0;
diff --git a/servers/text/text_server.cpp b/servers/text/text_server.cpp
index c58f46ee06..5341e49ad4 100644
--- a/servers/text/text_server.cpp
+++ b/servers/text/text_server.cpp
@@ -479,8 +479,9 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shaped_text_is_ready", "shaped"), &TextServer::shaped_text_is_ready);
ClassDB::bind_method(D_METHOD("shaped_text_has_visible_chars", "shaped"), &TextServer::shaped_text_has_visible_chars);
ClassDB::bind_method(D_METHOD("shaped_text_get_glyphs", "shaped"), &TextServer::_shaped_text_get_glyphs_wrapper);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_glyphs_ptr", "shaped"), &TextServer::_shaped_text_get_glyphs_gde_wrapper);
ClassDB::bind_method(D_METHOD("shaped_text_sort_logical", "shaped"), &TextServer::_shaped_text_sort_logical_wrapper);
ClassDB::bind_method(D_METHOD("shaped_text_get_glyph_count", "shaped"), &TextServer::shaped_text_get_glyph_count);
ClassDB::bind_method(D_METHOD("shaped_text_get_range", "shaped"), &TextServer::shaped_text_get_range);
@@ -2328,8 +2329,12 @@ TypedArray<Dictionary> TextServer::_shaped_text_get_glyphs_wrapper(const RID &p_
return ret;
}
+GDExtensionPtr<const Glyph> TextServer::_shaped_text_get_glyphs_gde_wrapper(const RID &p_shaped) const {
+ return GDExtensionPtr(shaped_text_get_glyphs(p_shaped));
+}
+
TypedArray<Dictionary> TextServer::_shaped_text_sort_logical_wrapper(const RID &p_shaped) {
Array ret;
const Glyph *glyphs = shaped_text_sort_logical(p_shaped);This will require a little change on the godot-cpp side as well:
diff --git a/binding_generator.py b/binding_generator.py
index 1629ba1..a8a8640 100644
--- a/binding_generator.py
+++ b/binding_generator.py
@@ -534,8 +534,14 @@ singletons = []
def generate_builtin_bindings(api, output_dir, build_config, hooks=None):
global builtin_classes
+ global native_structures
+
+ for native_struct in api["native_structures"]:
+ if native_struct["name"] == "ObjectID":
+ continue
+ native_structures.append(native_struct["name"])
core_gen_folder = Path(output_dir) / "include" / "godot_cpp" / "core"
include_gen_folder = Path(output_dir) / "include" / "godot_cpp" / "variant"
source_gen_folder = Path(output_dir) / "src" / "variant"
@@ -1409,12 +1415,15 @@ def generate_builtin_class_source(builtin_api, size, used_classes, fully_used_cl
is_ref = False
if "return_type" in method:
return_type = method["return_type"]
+ return_type_base = return_type.removeprefix("const ").removesuffix("*")
if is_enum(return_type):
method_call += f"return ({get_gdextension_type(correct_type(return_type))})::godot::internal::_call_builtin_method_ptr_ret<int64_t>("
elif is_pod_type(return_type) or is_variant(return_type):
method_call += f"return ::godot::internal::_call_builtin_method_ptr_ret<{get_gdextension_type(correct_type(return_type))}>("
+ elif return_type_base in native_structures:
+ method_call += f"return ::godot::internal::_call_builtin_method_ptr_ret<{return_type}>("
elif is_refcounted(return_type):
method_call += f"return Ref<{return_type}>::_gde_internal_constructor(::godot::internal::_call_builtin_method_ptr_ret_obj<{return_type}>("
is_ref = True
else:
@@ -1546,13 +1555,13 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node, hoo
if class_api["name"] in CLASS_ALIASES:
class_api["alias_for"] = class_api["name"]
class_api["name"] = CLASS_ALIASES[class_api["alias_for"]]
engine_classes[class_api["name"]] = class_api["is_refcounted"]
+
for native_struct in api["native_structures"]:
if native_struct["name"] == "ObjectID":
continue
engine_classes[native_struct["name"]] = False
- native_structures.append(native_struct["name"])
for singleton in api["singletons"]:
# Generate code for the ClassDB singleton under a different name.
if singleton["name"] in CLASS_ALIASES:
@@ -1760,10 +1769,10 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node, hoo
includes.sort()
for include in includes:
result.append(f"#include <{include}>")
- else:
- result.append("#include <godot_cpp/core/method_ptrcall.hpp>")
+
+ result.append("#include <godot_cpp/core/method_ptrcall.hpp>")
result.append("")
result.append("namespace godot {")
@@ -2218,8 +2227,9 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
is_ref = False
if not vararg:
if has_return:
return_type = method["return_value"]["type"]
+ return_type_base = return_type.removeprefix("const ").removesuffix("*")
meta_type = method["return_value"]["meta"] if "meta" in method["return_value"] else None
if is_enum(return_type):
if method["is_static"]:
method_call += f"return ({get_gdextension_type(correct_type(return_type, meta_type))})::godot::internal::_call_native_mb_ret<int64_t>(_gde_method_bind, nullptr"
@@ -2235,8 +2245,13 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us
method_call += f"return Ref<{return_type}>::_gde_internal_constructor(::godot::internal::_call_native_mb_ret_obj<{return_type}>(_gde_method_bind, nullptr"
else:
method_call += f"return Ref<{return_type}>::_gde_internal_constructor(::godot::internal::_call_native_mb_ret_obj<{return_type}>(_gde_method_bind, _owner"
is_ref = True
+ elif return_type_base in native_structures:
+ if method["is_static"]:
+ method_call += f"return ::godot::internal::_call_native_mb_ret<{get_gdextension_type(correct_type(return_type, meta_type))}>(_gde_method_bind, nullptr"
+ else:
+ method_call += f"return ::godot::internal::_call_native_mb_ret<{get_gdextension_type(correct_type(return_type, meta_type))}>(_gde_method_bind, _owner"
else:
if method["is_static"]:
method_call += f"return ::godot::internal::_call_native_mb_ret_obj<{return_type}>(_gde_method_bind, nullptr"
else:…ical,get_ellipsis_glyphs}` for gdextensions to use. Co-authored-by: bruvzg <7645683+bruvzg@users.noreply.github.com>
BenLubar
force-pushed
the
text-server-gdextension-nocopy-get-glyphs
branch
from
October 25, 2026 22:39
7d43edc to
cb5a16c
Compare
Contributor
Author
|
Was not aware that there was already (most of) the infrastructure for returning pointers from ClassDB methods in place. Thanks! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What problem(s) does this PR solve?
TextServermethods that returnGlyph *to the GDExtension interface godot-proposals#15240Additional Information
As mentioned in the proposal, this feels like a level-of-abstraction mismatch because nothing else outside of core is exposed in this way. That (and the fact that Godot is currently in feature freeze anyway) is why I'm submitting this as a draft for now.