diff options
Diffstat (limited to 'modules')
238 files changed, 3031 insertions, 1705 deletions
diff --git a/modules/camera/SCsub b/modules/camera/SCsub index de97724d09..9a6147d433 100644 --- a/modules/camera/SCsub +++ b/modules/camera/SCsub @@ -9,6 +9,6 @@ if env["platform"] == "windows": env_camera.add_source_files(env.modules_sources, "register_types.cpp") env_camera.add_source_files(env.modules_sources, "camera_win.cpp") -elif env["platform"] == "osx": +elif env["platform"] == "macos": env_camera.add_source_files(env.modules_sources, "register_types.cpp") - env_camera.add_source_files(env.modules_sources, "camera_osx.mm") + env_camera.add_source_files(env.modules_sources, "camera_macos.mm") diff --git a/modules/camera/camera_osx.h b/modules/camera/camera_macos.h index b0db844599..903eda51bf 100644 --- a/modules/camera/camera_osx.h +++ b/modules/camera/camera_macos.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* camera_osx.h */ +/* camera_macos.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,19 +28,19 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CAMERAOSX_H -#define CAMERAOSX_H +#ifndef CAMERA_MACOS_H +#define CAMERA_MACOS_H ///@TODO this is a near duplicate of CameraIOS, we should find a way to combine those to minimize code duplication!!!! // If you fix something here, make sure you fix it there as well! #include "servers/camera_server.h" -class CameraOSX : public CameraServer { +class CameraMacOS : public CameraServer { public: - CameraOSX(); + CameraMacOS(); void update_feeds(); }; -#endif /* CAMERAOSX_H */ +#endif // CAMERA_MACOS_H diff --git a/modules/camera/camera_osx.mm b/modules/camera/camera_macos.mm index d199c31b2f..0b9696a3e9 100644 --- a/modules/camera/camera_osx.mm +++ b/modules/camera/camera_macos.mm @@ -1,5 +1,5 @@ /*************************************************************************/ -/* camera_osx.mm */ +/* camera_macos.mm */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -31,7 +31,7 @@ ///@TODO this is a near duplicate of CameraIOS, we should find a way to combine those to minimize code duplication!!!! // If you fix something here, make sure you fix it there as well! -#include "camera_osx.h" +#include "camera_macos.h" #include "servers/camera/camera_feed.h" #import <AVFoundation/AVFoundation.h> @@ -191,9 +191,9 @@ @end ////////////////////////////////////////////////////////////////////////// -// CameraFeedOSX - Subclass for camera feeds in OSX +// CameraFeedMacOS - Subclass for camera feeds in macOS -class CameraFeedOSX : public CameraFeed { +class CameraFeedMacOS : public CameraFeed { private: AVCaptureDevice *device; MyCaptureSession *capture_session; @@ -201,7 +201,7 @@ private: public: AVCaptureDevice *get_device() const; - CameraFeedOSX(); + CameraFeedMacOS(); void set_device(AVCaptureDevice *p_device); @@ -209,16 +209,16 @@ public: void deactivate_feed(); }; -AVCaptureDevice *CameraFeedOSX::get_device() const { +AVCaptureDevice *CameraFeedMacOS::get_device() const { return device; }; -CameraFeedOSX::CameraFeedOSX() { +CameraFeedMacOS::CameraFeedMacOS() { device = nullptr; capture_session = nullptr; }; -void CameraFeedOSX::set_device(AVCaptureDevice *p_device) { +void CameraFeedMacOS::set_device(AVCaptureDevice *p_device) { device = p_device; // get some info @@ -232,7 +232,7 @@ void CameraFeedOSX::set_device(AVCaptureDevice *p_device) { }; }; -bool CameraFeedOSX::activate_feed() { +bool CameraFeedMacOS::activate_feed() { if (capture_session) { // Already recording! } else { @@ -258,7 +258,7 @@ bool CameraFeedOSX::activate_feed() { return true; }; -void CameraFeedOSX::deactivate_feed() { +void CameraFeedMacOS::deactivate_feed() { // end camera capture if we have one if (capture_session) { [capture_session cleanup]; @@ -271,7 +271,7 @@ void CameraFeedOSX::deactivate_feed() { // when devices are connected/disconnected @interface MyDeviceNotifications : NSObject { - CameraOSX *camera_server; + CameraMacOS *camera_server; } @end @@ -282,7 +282,7 @@ void CameraFeedOSX::deactivate_feed() { camera_server->update_feeds(); } -- (id)initForServer:(CameraOSX *)p_server { +- (id)initForServer:(CameraMacOS *)p_server { if (self = [super init]) { camera_server = p_server; @@ -303,9 +303,9 @@ void CameraFeedOSX::deactivate_feed() { MyDeviceNotifications *device_notifications = nil; ////////////////////////////////////////////////////////////////////////// -// CameraOSX - Subclass for our camera server on OSX +// CameraMacOS - Subclass for our camera server on macOS -void CameraOSX::update_feeds() { +void CameraMacOS::update_feeds() { #if MAC_OS_X_VERSION_MIN_REQUIRED >= 101500 AVCaptureDeviceDiscoverySession *session = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:[NSArray arrayWithObjects:AVCaptureDeviceTypeExternalUnknown, AVCaptureDeviceTypeBuiltInWideAngleCamera, nil] mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionUnspecified]; NSArray *devices = session.devices; @@ -315,7 +315,7 @@ void CameraOSX::update_feeds() { // remove devices that are gone.. for (int i = feeds.size() - 1; i >= 0; i--) { - Ref<CameraFeedOSX> feed = (Ref<CameraFeedOSX>)feeds[i]; + Ref<CameraFeedMacOS> feed = (Ref<CameraFeedMacOS>)feeds[i]; if (![devices containsObject:feed->get_device()]) { // remove it from our array, this will also destroy it ;) @@ -326,14 +326,14 @@ void CameraOSX::update_feeds() { for (AVCaptureDevice *device in devices) { bool found = false; for (int i = 0; i < feeds.size() && !found; i++) { - Ref<CameraFeedOSX> feed = (Ref<CameraFeedOSX>)feeds[i]; + Ref<CameraFeedMacOS> feed = (Ref<CameraFeedMacOS>)feeds[i]; if (feed->get_device() == device) { found = true; }; }; if (!found) { - Ref<CameraFeedOSX> newfeed; + Ref<CameraFeedMacOS> newfeed; newfeed.instantiate(); newfeed->set_device(device); @@ -346,7 +346,7 @@ void CameraOSX::update_feeds() { }; }; -CameraOSX::CameraOSX() { +CameraMacOS::CameraMacOS() { // Find available cameras we have at this time update_feeds(); diff --git a/modules/camera/camera_win.h b/modules/camera/camera_win.h index 9563326acb..ebfc117190 100644 --- a/modules/camera/camera_win.h +++ b/modules/camera/camera_win.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CAMERAWIN_H -#define CAMERAWIN_H +#ifndef CAMERA_WIN_H +#define CAMERA_WIN_H #include "servers/camera/camera_feed.h" #include "servers/camera_server.h" @@ -43,4 +43,4 @@ public: ~CameraWindows() {} }; -#endif /* CAMERAWIN_H */ +#endif // CAMERA_WIN_H diff --git a/modules/camera/config.py b/modules/camera/config.py index 8a22751aa7..d2b2542dd9 100644 --- a/modules/camera/config.py +++ b/modules/camera/config.py @@ -1,5 +1,5 @@ def can_build(env, platform): - return platform == "osx" or platform == "windows" + return platform == "macos" or platform == "windows" def configure(env): diff --git a/modules/camera/register_types.cpp b/modules/camera/register_types.cpp index 98a4b5ca1a..40e2224d6b 100644 --- a/modules/camera/register_types.cpp +++ b/modules/camera/register_types.cpp @@ -33,8 +33,8 @@ #if defined(WINDOWS_ENABLED) #include "camera_win.h" #endif -#if defined(OSX_ENABLED) -#include "camera_osx.h" +#if defined(MACOS_ENABLED) +#include "camera_macos.h" #endif void initialize_camera_module(ModuleInitializationLevel p_level) { @@ -45,8 +45,8 @@ void initialize_camera_module(ModuleInitializationLevel p_level) { #if defined(WINDOWS_ENABLED) CameraServer::make_default<CameraWindows>(); #endif -#if defined(OSX_ENABLED) - CameraServer::make_default<CameraOSX>(); +#if defined(MACOS_ENABLED) + CameraServer::make_default<CameraMacOS>(); #endif } diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index 0f09eb2020..56be4e65f0 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -1858,7 +1858,7 @@ CSGBrush *CSGPolygon3D::_build_brush() { } Transform3D facing = Transform3D().looking_at(direction, current_up); - current_xform = base_xform.translated(current_point) * facing; + current_xform = base_xform.translated_local(current_point) * facing; } // Create the mesh. @@ -1897,7 +1897,7 @@ CSGBrush *CSGPolygon3D::_build_brush() { switch (mode) { case MODE_DEPTH: { - current_xform.translate(Vector3(0, 0, -depth)); + current_xform.translate_local(Vector3(0, 0, -depth)); } break; case MODE_SPIN: { current_xform.rotate(Vector3(0, 1, 0), spin_step); @@ -1945,7 +1945,7 @@ CSGBrush *CSGPolygon3D::_build_brush() { } Transform3D facing = Transform3D().looking_at(direction, current_up); - current_xform = base_xform.translated(current_point) * facing; + current_xform = base_xform.translated_local(current_point) * facing; } break; } diff --git a/modules/dds/texture_loader_dds.cpp b/modules/dds/texture_loader_dds.cpp index 2c0e604e66..eb5614338b 100644 --- a/modules/dds/texture_loader_dds.cpp +++ b/modules/dds/texture_loader_dds.cpp @@ -409,9 +409,7 @@ Ref<Resource> ResourceFormatDDS::load(const String &p_path, const String &p_orig } Ref<Image> img = memnew(Image(width, height, mipmaps - 1, info.format, src_data)); - - Ref<ImageTexture> texture = memnew(ImageTexture); - texture->create_from_image(img); + Ref<ImageTexture> texture = ImageTexture::create_from_image(img); if (r_error) { *r_error = OK; diff --git a/modules/denoise/config.py b/modules/denoise/config.py index 3aa840acb0..521115dae5 100644 --- a/modules/denoise/config.py +++ b/modules/denoise/config.py @@ -4,7 +4,7 @@ def can_build(env, platform): # It's also only relevant for tools build and desktop platforms, # as doing lightmap generation and denoising on Android or HTML5 # would be a bit far-fetched. - desktop_platforms = ["linuxbsd", "osx", "windows"] + desktop_platforms = ["linuxbsd", "macos", "windows"] supported_arch = env["bits"] == "64" if env["arch"] == "arm64": supported_arch = False diff --git a/modules/enet/enet_multiplayer_peer.h b/modules/enet/enet_multiplayer_peer.h index 18eca18e51..131aa04df1 100644 --- a/modules/enet/enet_multiplayer_peer.h +++ b/modules/enet/enet_multiplayer_peer.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef NETWORKED_MULTIPLAYER_ENET_H -#define NETWORKED_MULTIPLAYER_ENET_H +#ifndef ENET_MULTIPLAYER_PEER_H +#define ENET_MULTIPLAYER_PEER_H #include "core/crypto/crypto.h" #include "core/multiplayer/multiplayer_peer.h" @@ -135,4 +135,4 @@ public: ~ENetMultiplayerPeer(); }; -#endif // NETWORKED_MULTIPLAYER_ENET_H +#endif // ENET_MULTIPLAYER_PEER_H diff --git a/modules/freetype/uwpdef.h b/modules/freetype/uwpdef.h index 05aaae61b5..f85f293171 100644 --- a/modules/freetype/uwpdef.h +++ b/modules/freetype/uwpdef.h @@ -28,6 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef UWPDEF_H +#define UWPDEF_H + // "generic" is a reserved keyword in C++/CX code // this avoids the errors in the variable name from Freetype code #define generic freetype_generic + +#endif // UWPDEF_H diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index 70151c4d21..10cf783e73 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -144,6 +144,7 @@ [/codeblock] [b]Important:[/b] The path must be absolute, a local path will just return [code]null[/code]. This method is a simplified version of [method ResourceLoader.load], which can be used for more advanced scenarios. + [b]Note:[/b] You have to import the files into the engine first to load them using [method load]. If you want to load [Image]s at run-time, you may use [method Image.load]. If you want to import audio files, you can use the snippet described in [member AudioStreamMP3.data]. </description> </method> <method name="preload"> @@ -257,4 +258,162 @@ [b]Note:[/b] "Not a Number" is only a concept with floating-point numbers, and has no equivalent for integers. Dividing an integer [code]0[/code] by [code]0[/code] will not result in [constant NAN] and will result in a run-time error instead. </constant> </constants> + <annotations> + <annotation name="@export"> + <return type="void" /> + <description> + </description> + </annotation> + <annotation name="@export_category"> + <return type="void" /> + <argument index="0" name="name" type="String" /> + <description> + </description> + </annotation> + <annotation name="@export_color_no_alpha"> + <return type="void" /> + <description> + </description> + </annotation> + <annotation name="@export_dir"> + <return type="void" /> + <description> + </description> + </annotation> + <annotation name="@export_enum" qualifiers="vararg"> + <return type="void" /> + <argument index="0" name="names" type="String" /> + <description> + </description> + </annotation> + <annotation name="@export_exp_easing" qualifiers="vararg"> + <return type="void" /> + <argument index="0" name="hints" type="String" default="""" /> + <description> + </description> + </annotation> + <annotation name="@export_file" qualifiers="vararg"> + <return type="void" /> + <argument index="0" name="filter" type="String" default="""" /> + <description> + </description> + </annotation> + <annotation name="@export_flags" qualifiers="vararg"> + <return type="void" /> + <argument index="0" name="names" type="String" /> + <description> + </description> + </annotation> + <annotation name="@export_flags_2d_navigation"> + <return type="void" /> + <description> + </description> + </annotation> + <annotation name="@export_flags_2d_physics"> + <return type="void" /> + <description> + </description> + </annotation> + <annotation name="@export_flags_2d_render"> + <return type="void" /> + <description> + </description> + </annotation> + <annotation name="@export_flags_3d_navigation"> + <return type="void" /> + <description> + </description> + </annotation> + <annotation name="@export_flags_3d_physics"> + <return type="void" /> + <description> + </description> + </annotation> + <annotation name="@export_flags_3d_render"> + <return type="void" /> + <description> + </description> + </annotation> + <annotation name="@export_global_dir"> + <return type="void" /> + <description> + </description> + </annotation> + <annotation name="@export_global_file" qualifiers="vararg"> + <return type="void" /> + <argument index="0" name="filter" type="String" default="""" /> + <description> + </description> + </annotation> + <annotation name="@export_group"> + <return type="void" /> + <argument index="0" name="name" type="String" /> + <argument index="1" name="prefix" type="String" default="""" /> + <description> + </description> + </annotation> + <annotation name="@export_multiline"> + <return type="void" /> + <description> + </description> + </annotation> + <annotation name="@export_node_path" qualifiers="vararg"> + <return type="void" /> + <argument index="0" name="type" type="String" default="""" /> + <description> + </description> + </annotation> + <annotation name="@export_placeholder"> + <return type="void" /> + <description> + </description> + </annotation> + <annotation name="@export_range" qualifiers="vararg"> + <return type="void" /> + <argument index="0" name="min" type="float" /> + <argument index="1" name="max" type="float" /> + <argument index="2" name="step" type="float" default="1.0" /> + <argument index="3" name="extra_hints" type="String" default="""" /> + <description> + </description> + </annotation> + <annotation name="@export_subgroup"> + <return type="void" /> + <argument index="0" name="name" type="String" /> + <argument index="1" name="prefix" type="String" default="""" /> + <description> + </description> + </annotation> + <annotation name="@icon"> + <return type="void" /> + <argument index="0" name="icon_path" type="String" /> + <description> + </description> + </annotation> + <annotation name="@onready"> + <return type="void" /> + <description> + </description> + </annotation> + <annotation name="@rpc" qualifiers="vararg"> + <return type="void" /> + <argument index="0" name="mode" type="String" default="""" /> + <argument index="1" name="sync" type="String" default="""" /> + <argument index="2" name="transfer_mode" type="String" default="""" /> + <argument index="3" name="transfer_channel" type="int" default="0" /> + <description> + </description> + </annotation> + <annotation name="@tool"> + <return type="void" /> + <description> + </description> + </annotation> + <annotation name="@warning_ignore" qualifiers="vararg"> + <return type="void" /> + <argument index="0" name="warning" type="String" /> + <description> + </description> + </annotation> + </annotations> </class> diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index b86e9b386d..4372bb33ba 100644 --- a/modules/gdscript/editor/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -55,7 +55,9 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l bool in_function_args = false; bool in_member_variable = false; bool in_node_path = false; + bool in_node_ref = false; bool in_annotation = false; + bool in_string_name = false; bool is_hex_notation = false; bool is_bin_notation = false; bool expect_type = false; @@ -165,6 +167,12 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l if (in_node_path && (color_regions[in_region].start_key == "\"" || color_regions[in_region].start_key == "\'")) { region_color = node_path_color; } + if (in_node_ref && (color_regions[in_region].start_key == "\"" || color_regions[in_region].start_key == "\'")) { + region_color = node_ref_color; + } + if (in_string_name && (color_regions[in_region].start_key == "\"" || color_regions[in_region].start_key == "\'")) { + region_color = string_name_color; + } prev_color = region_color; highlighter_info["color"] = region_color; @@ -387,24 +395,42 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l in_member_variable = false; } - if (!in_node_path && in_region == -1 && (str[j] == '$' || str[j] == '%')) { + if (!in_node_path && in_region == -1 && (str[j] == '^')) { in_node_path = true; } else if (in_region != -1 || (is_a_symbol && str[j] != '/' && str[j] != '%')) { in_node_path = false; } + if (!in_node_ref && in_region == -1 && (str[j] == '$' || str[j] == '%')) { + in_node_ref = true; + } else if (in_region != -1 || (is_a_symbol && str[j] != '/' && str[j] != '%')) { + in_node_ref = false; + } + if (!in_annotation && in_region == -1 && str[j] == '@') { in_annotation = true; } else if (in_region != -1 || is_a_symbol) { in_annotation = false; } + if (!in_string_name && in_region == -1 && str[j] == '&') { + in_string_name = true; + } else if (in_region != -1 || is_a_symbol) { + in_string_name = false; + } + if (in_node_path) { next_type = NODE_PATH; color = node_path_color; + } else if (in_node_ref) { + next_type = NODE_REF; + color = node_ref_color; } else if (in_annotation) { next_type = ANNOTATION; color = annotation_color; + } else if (in_string_name) { + next_type = STRING_NAME; + color = string_name_color; } else if (in_keyword) { next_type = KEYWORD; color = keyword_color; @@ -592,17 +618,23 @@ void GDScriptSyntaxHighlighter::_update_cache() { if (godot_2_theme || EditorSettings::get_singleton()->is_dark_theme()) { function_definition_color = Color(0.4, 0.9, 1.0); - node_path_color = Color(0.39, 0.76, 0.35); + node_path_color = Color(0.72, 0.77, 0.49); + node_ref_color = Color(0.39, 0.76, 0.35); annotation_color = Color(1.0, 0.7, 0.45); + string_name_color = Color(1.0, 0.66, 0.72); } else { function_definition_color = Color(0.0, 0.65, 0.73); - node_path_color = Color(0.32, 0.55, 0.29); + node_path_color = Color(0.62, 0.67, 0.39); + node_ref_color = Color(0.32, 0.55, 0.29); annotation_color = Color(0.8, 0.5, 0.25); + string_name_color = Color(0.9, 0.56, 0.62); } EDITOR_DEF("text_editor/theme/highlighting/gdscript/function_definition_color", function_definition_color); EDITOR_DEF("text_editor/theme/highlighting/gdscript/node_path_color", node_path_color); + EDITOR_DEF("text_editor/theme/highlighting/gdscript/node_reference_color", node_ref_color); EDITOR_DEF("text_editor/theme/highlighting/gdscript/annotation_color", annotation_color); + EDITOR_DEF("text_editor/theme/highlighting/gdscript/string_name_color", string_name_color); if (text_edit_color_theme == "Default" || godot_2_theme) { EditorSettings::get_singleton()->set_initial_value( "text_editor/theme/highlighting/gdscript/function_definition_color", @@ -613,14 +645,24 @@ void GDScriptSyntaxHighlighter::_update_cache() { node_path_color, true); EditorSettings::get_singleton()->set_initial_value( + "text_editor/theme/highlighting/gdscript/node_reference_color", + node_ref_color, + true); + EditorSettings::get_singleton()->set_initial_value( "text_editor/theme/highlighting/gdscript/annotation_color", annotation_color, true); + EditorSettings::get_singleton()->set_initial_value( + "text_editor/theme/highlighting/gdscript/string_name_color", + string_name_color, + true); } function_definition_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/function_definition_color"); node_path_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/node_path_color"); + node_ref_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/node_reference_color"); annotation_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/annotation_color"); + string_name_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/string_name_color"); type_color = EDITOR_GET("text_editor/theme/highlighting/base_type_color"); } diff --git a/modules/gdscript/editor/gdscript_highlighter.h b/modules/gdscript/editor/gdscript_highlighter.h index 92764e3891..7987582f07 100644 --- a/modules/gdscript/editor/gdscript_highlighter.h +++ b/modules/gdscript/editor/gdscript_highlighter.h @@ -54,7 +54,9 @@ private: NONE, REGION, NODE_PATH, + NODE_REF, ANNOTATION, + STRING_NAME, SYMBOL, NUMBER, FUNCTION, @@ -74,7 +76,9 @@ private: Color number_color; Color member_color; Color node_path_color; + Color node_ref_color; Color annotation_color; + Color string_name_color; Color type_color; void add_color_region(const String &p_start_key, const String &p_end_key, const Color &p_color, bool p_line_only = false); diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index e6aeef2fd1..a34bf6ef82 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -278,6 +278,11 @@ void GDScript::_get_script_method_list(List<MethodInfo> *r_list, bool p_include_ GDScriptFunction *func = E.value; MethodInfo mi; mi.name = E.key; + + if (func->is_static()) { + mi.flags |= METHOD_FLAG_STATIC; + } + for (int i = 0; i < func->get_argument_count(); i++) { PropertyInfo arginfo = func->get_argument_type(i); #ifdef TOOLS_ENABLED @@ -536,6 +541,9 @@ void GDScript::_update_doc() { List<PropertyInfo> props; _get_script_property_list(&props, false); for (int i = 0; i < props.size(); i++) { + if (props[i].usage & PROPERTY_USAGE_CATEGORY || props[i].usage & PROPERTY_USAGE_GROUP || props[i].usage & PROPERTY_USAGE_SUBGROUP) { + continue; + } ScriptMemberInfo scr_member_info; scr_member_info.propinfo = props[i]; scr_member_info.propinfo.usage |= PROPERTY_USAGE_NIL_IS_VARIANT; @@ -867,7 +875,7 @@ Error GDScript::reload(bool p_keep_state) { } // TODO: Show all error messages. _err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), parser.get_errors().front()->get().line, ("Parse Error: " + parser.get_errors().front()->get().message).utf8().get_data(), false, ERR_HANDLER_SCRIPT); - ERR_FAIL_V(ERR_PARSE_ERROR); + return ERR_PARSE_ERROR; } GDScriptAnalyzer analyzer(&parser); @@ -883,7 +891,7 @@ Error GDScript::reload(bool p_keep_state) { _err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), e->get().line, ("Parse Error: " + e->get().message).utf8().get_data(), false, ERR_HANDLER_SCRIPT); e = e->next(); } - ERR_FAIL_V(ERR_PARSE_ERROR); + return ERR_PARSE_ERROR; } bool can_run = ScriptServer::is_scripting_enabled() || parser.is_tool(); @@ -901,7 +909,7 @@ Error GDScript::reload(bool p_keep_state) { GDScriptLanguage::get_singleton()->debug_break_parse(_get_debug_path(), compiler.get_error_line(), "Parser Error: " + compiler.get_error()); } _err_print_error("GDScript::reload", path.is_empty() ? "built-in" : (const char *)path.utf8().get_data(), compiler.get_error_line(), ("Compile Error: " + compiler.get_error()).utf8().get_data(), false, ERR_HANDLER_SCRIPT); - ERR_FAIL_V(ERR_COMPILATION_FAILED); + return ERR_COMPILATION_FAILED; } else { return err; } @@ -1050,7 +1058,7 @@ Error GDScript::load_source_code(const String &p_path) { w[len] = 0; String s; - if (s.parse_utf8((const char *)w)) { + if (s.parse_utf8((const char *)w) != OK) { ERR_FAIL_V_MSG(ERR_INVALID_DATA, "Script '" + p_path + "' contains invalid unicode (UTF-8), so it was not loaded. Please ensure that scripts are saved in valid UTF-8 unicode."); } @@ -1524,7 +1532,6 @@ void GDScriptInstance::get_method_list(List<MethodInfo> *p_list) const { for (const KeyValue<StringName, GDScriptFunction *> &E : sptr->member_functions) { MethodInfo mi; mi.name = E.key; - mi.flags |= METHOD_FLAG_FROM_SCRIPT; for (int i = 0; i < E.value->get_argument_count(); i++) { mi.arguments.push_back(PropertyInfo(Variant::NIL, "arg" + itos(i))); } diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index feb0a237df..e9a206f48b 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -489,6 +489,7 @@ public: virtual void get_public_functions(List<MethodInfo> *p_functions) const override; virtual void get_public_constants(List<Pair<String, Variant>> *p_constants) const override; + virtual void get_public_annotations(List<MethodInfo> *p_annotations) const override; virtual void profiling_start() override; virtual void profiling_stop() override; diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index ea994654bf..7ed440929c 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -655,43 +655,43 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas } else { ERR_PRINT("Parser bug (please report): tried to assign unset node without an identifier."); } - } else { - if (member.variable->datatype_specifier != nullptr) { - datatype = specified_type; + } - if (member.variable->initializer != nullptr) { - if (!is_type_compatible(datatype, member.variable->initializer->get_datatype(), true, member.variable->initializer)) { - // Try reverse test since it can be a masked subtype. - if (!is_type_compatible(member.variable->initializer->get_datatype(), datatype, true, member.variable->initializer)) { - push_error(vformat(R"(Value of type "%s" cannot be assigned to a variable of type "%s".)", member.variable->initializer->get_datatype().to_string(), datatype.to_string()), member.variable->initializer); - } else { - // TODO: Add warning. - mark_node_unsafe(member.variable->initializer); - member.variable->use_conversion_assign = true; - } - } else if (datatype.builtin_type == Variant::INT && member.variable->initializer->get_datatype().builtin_type == Variant::FLOAT) { -#ifdef DEBUG_ENABLED - parser->push_warning(member.variable->initializer, GDScriptWarning::NARROWING_CONVERSION); -#endif - } - if (member.variable->initializer->get_datatype().is_variant()) { - // TODO: Warn unsafe assign. + if (member.variable->datatype_specifier != nullptr) { + datatype = specified_type; + + if (member.variable->initializer != nullptr) { + if (!is_type_compatible(datatype, member.variable->initializer->get_datatype(), true, member.variable->initializer)) { + // Try reverse test since it can be a masked subtype. + if (!is_type_compatible(member.variable->initializer->get_datatype(), datatype, true, member.variable->initializer)) { + push_error(vformat(R"(Value of type "%s" cannot be assigned to a variable of type "%s".)", member.variable->initializer->get_datatype().to_string(), datatype.to_string()), member.variable->initializer); + } else { + // TODO: Add warning. mark_node_unsafe(member.variable->initializer); member.variable->use_conversion_assign = true; } + } else if (datatype.builtin_type == Variant::INT && member.variable->initializer->get_datatype().builtin_type == Variant::FLOAT) { +#ifdef DEBUG_ENABLED + parser->push_warning(member.variable->initializer, GDScriptWarning::NARROWING_CONVERSION); +#endif } - } else if (member.variable->infer_datatype) { - if (member.variable->initializer == nullptr) { - push_error(vformat(R"(Cannot infer the type of "%s" variable because there's no default value.)", member.variable->identifier->name), member.variable->identifier); - } else if (!datatype.is_set() || datatype.has_no_type()) { - push_error(vformat(R"(Cannot infer the type of "%s" variable because the initial value doesn't have a set type.)", member.variable->identifier->name), member.variable->initializer); - } else if (datatype.is_variant()) { - push_error(vformat(R"(Cannot infer the type of "%s" variable because the initial value is Variant. Use explicit "Variant" type if this is intended.)", member.variable->identifier->name), member.variable->initializer); - } else if (datatype.builtin_type == Variant::NIL) { - push_error(vformat(R"(Cannot infer the type of "%s" variable because the initial value is "null".)", member.variable->identifier->name), member.variable->initializer); + if (member.variable->initializer->get_datatype().is_variant()) { + // TODO: Warn unsafe assign. + mark_node_unsafe(member.variable->initializer); + member.variable->use_conversion_assign = true; } - datatype.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED; } + } else if (member.variable->infer_datatype) { + if (member.variable->initializer == nullptr) { + push_error(vformat(R"(Cannot infer the type of "%s" variable because there's no default value.)", member.variable->identifier->name), member.variable->identifier); + } else if (!datatype.is_set() || datatype.has_no_type()) { + push_error(vformat(R"(Cannot infer the type of "%s" variable because the initial value doesn't have a set type.)", member.variable->identifier->name), member.variable->initializer); + } else if (datatype.is_variant()) { + push_error(vformat(R"(Cannot infer the type of "%s" variable because the initial value is Variant. Use explicit "Variant" type if this is intended.)", member.variable->identifier->name), member.variable->initializer); + } else if (datatype.builtin_type == Variant::NIL) { + push_error(vformat(R"(Cannot infer the type of "%s" variable because the initial value is "null".)", member.variable->identifier->name), member.variable->initializer); + } + datatype.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED; } datatype.is_constant = false; @@ -860,6 +860,9 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas case GDScriptParser::ClassNode::Member::CLASS: check_class_member_name_conflict(p_class, member.m_class->identifier->name, member.m_class); break; + case GDScriptParser::ClassNode::Member::GROUP: + // No-op, but needed to silence warnings. + break; case GDScriptParser::ClassNode::Member::UNDEFINED: ERR_PRINT("Trying to resolve undefined member."); break; @@ -3326,8 +3329,11 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri case Variant::VECTOR2I: case Variant::VECTOR3: case Variant::VECTOR3I: + case Variant::VECTOR4: + case Variant::VECTOR4I: case Variant::TRANSFORM2D: case Variant::TRANSFORM3D: + case Variant::PROJECTION: error = index_type.builtin_type != Variant::INT && index_type.builtin_type != Variant::FLOAT && index_type.builtin_type != Variant::STRING; break; @@ -3390,6 +3396,7 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri case Variant::PACKED_INT64_ARRAY: case Variant::VECTOR2I: case Variant::VECTOR3I: + case Variant::VECTOR4I: result_type.builtin_type = Variant::INT; break; // Return float. @@ -3397,6 +3404,7 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri case Variant::PACKED_FLOAT64_ARRAY: case Variant::VECTOR2: case Variant::VECTOR3: + case Variant::VECTOR4: case Variant::QUATERNION: result_type.builtin_type = Variant::FLOAT; break; @@ -3427,6 +3435,7 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri break; // Depends on the index. case Variant::TRANSFORM3D: + case Variant::PROJECTION: case Variant::PLANE: case Variant::COLOR: case Variant::DICTIONARY: diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp index 6a1effd680..8e4ca44e81 100644 --- a/modules/gdscript/gdscript_byte_codegen.cpp +++ b/modules/gdscript/gdscript_byte_codegen.cpp @@ -84,11 +84,14 @@ uint32_t GDScriptByteCodeGenerator::add_temporary(const GDScriptDataType &p_type case Variant::VECTOR3: case Variant::VECTOR3I: case Variant::TRANSFORM2D: + case Variant::VECTOR4: + case Variant::VECTOR4I: case Variant::PLANE: case Variant::QUATERNION: case Variant::AABB: case Variant::BASIS: case Variant::TRANSFORM3D: + case Variant::PROJECTION: case Variant::COLOR: case Variant::STRING_NAME: case Variant::NODE_PATH: @@ -453,6 +456,12 @@ void GDScriptByteCodeGenerator::write_type_adjust(const Address &p_target, Varia case Variant::TRANSFORM2D: append(GDScriptFunction::OPCODE_TYPE_ADJUST_TRANSFORM2D, 1); break; + case Variant::VECTOR4: + append(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR3, 1); + break; + case Variant::VECTOR4I: + append(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR3I, 1); + break; case Variant::PLANE: append(GDScriptFunction::OPCODE_TYPE_ADJUST_PLANE, 1); break; @@ -468,6 +477,9 @@ void GDScriptByteCodeGenerator::write_type_adjust(const Address &p_target, Varia case Variant::TRANSFORM3D: append(GDScriptFunction::OPCODE_TYPE_ADJUST_TRANSFORM3D, 1); break; + case Variant::PROJECTION: + append(GDScriptFunction::OPCODE_TYPE_ADJUST_PROJECTION, 1); + break; case Variant::COLOR: append(GDScriptFunction::OPCODE_TYPE_ADJUST_COLOR, 1); break; @@ -1596,7 +1608,7 @@ void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) { // Typed array. const GDScriptDataType &element_type = function->return_type.get_container_element_type(); - Variant script = function->return_type.script_type; + Variant script = element_type.script_type; int script_idx = get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS); append(GDScriptFunction::OPCODE_RETURN_TYPED_ARRAY, 2); diff --git a/modules/gdscript/gdscript_byte_codegen.h b/modules/gdscript/gdscript_byte_codegen.h index f4b402fc96..ffc3178c83 100644 --- a/modules/gdscript/gdscript_byte_codegen.h +++ b/modules/gdscript/gdscript_byte_codegen.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GDSCRIPT_BYTE_CODEGEN -#define GDSCRIPT_BYTE_CODEGEN +#ifndef GDSCRIPT_BYTE_CODEGEN_H +#define GDSCRIPT_BYTE_CODEGEN_H #include "gdscript_codegen.h" @@ -502,4 +502,4 @@ public: virtual ~GDScriptByteCodeGenerator(); }; -#endif // GDSCRIPT_BYTE_CODEGEN +#endif // GDSCRIPT_BYTE_CODEGEN_H diff --git a/modules/gdscript/gdscript_cache.cpp b/modules/gdscript/gdscript_cache.cpp index 4c15fca91e..48d5fbc569 100644 --- a/modules/gdscript/gdscript_cache.cpp +++ b/modules/gdscript/gdscript_cache.cpp @@ -157,7 +157,7 @@ String GDScriptCache::get_source_code(const String &p_path) { source_file.write[len] = 0; String source; - if (source.parse_utf8((const char *)source_file.ptr())) { + if (source.parse_utf8((const char *)source_file.ptr()) != OK) { ERR_FAIL_V_MSG("", "Script '" + p_path + "' contains invalid unicode (UTF-8), so it was not loaded. Please ensure that scripts are saved in valid UTF-8 unicode."); } return source; diff --git a/modules/gdscript/gdscript_codegen.h b/modules/gdscript/gdscript_codegen.h index 81fa265aca..7b5f133ec5 100644 --- a/modules/gdscript/gdscript_codegen.h +++ b/modules/gdscript/gdscript_codegen.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GDSCRIPT_CODEGEN -#define GDSCRIPT_CODEGEN +#ifndef GDSCRIPT_CODEGEN_H +#define GDSCRIPT_CODEGEN_H #include "core/multiplayer/multiplayer.h" #include "core/string/string_name.h" @@ -163,4 +163,4 @@ public: virtual ~GDScriptCodeGenerator() {} }; -#endif // GDSCRIPT_CODEGEN +#endif // GDSCRIPT_CODEGEN_H diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 6055d3df33..e36252ada5 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -43,7 +43,7 @@ bool GDScriptCompiler::_is_class_member_property(CodeGen &codegen, const StringN return false; } - if (codegen.locals.has(p_name)) { + if (codegen.parameters.has(p_name) || codegen.locals.has(p_name)) { return false; //shadowed } @@ -2452,6 +2452,25 @@ Error GDScriptCompiler::_parse_class_level(GDScript *p_script, const GDScriptPar } #endif } break; + + case GDScriptParser::ClassNode::Member::GROUP: { + const GDScriptParser::AnnotationNode *annotation = member.annotation; + StringName name = annotation->export_info.name; + + // This is not a normal member, but we need this to keep indices in order. + GDScript::MemberInfo minfo; + minfo.index = p_script->member_indices.size(); + + PropertyInfo prop_info; + prop_info.name = name; + prop_info.usage = annotation->export_info.usage; + prop_info.hint_string = annotation->export_info.hint_string; + + p_script->member_info[name] = prop_info; + p_script->member_indices[name] = minfo; + p_script->members.insert(name); + } break; + default: break; // Nothing to do here. } diff --git a/modules/gdscript/gdscript_disassembler.cpp b/modules/gdscript/gdscript_disassembler.cpp index 726f0efe2b..b38c7c6699 100644 --- a/modules/gdscript/gdscript_disassembler.cpp +++ b/modules/gdscript/gdscript_disassembler.cpp @@ -639,10 +639,13 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { DISASSEMBLE_PTRCALL(VECTOR3); DISASSEMBLE_PTRCALL(VECTOR3I); DISASSEMBLE_PTRCALL(TRANSFORM2D); + DISASSEMBLE_PTRCALL(VECTOR4); + DISASSEMBLE_PTRCALL(VECTOR4I); DISASSEMBLE_PTRCALL(PLANE); DISASSEMBLE_PTRCALL(AABB); DISASSEMBLE_PTRCALL(BASIS); DISASSEMBLE_PTRCALL(TRANSFORM3D); + DISASSEMBLE_PTRCALL(PROJECTION); DISASSEMBLE_PTRCALL(COLOR); DISASSEMBLE_PTRCALL(STRING_NAME); DISASSEMBLE_PTRCALL(NODE_PATH); @@ -1013,11 +1016,14 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const { DISASSEMBLE_TYPE_ADJUST(VECTOR3); DISASSEMBLE_TYPE_ADJUST(VECTOR3I); DISASSEMBLE_TYPE_ADJUST(TRANSFORM2D); + DISASSEMBLE_TYPE_ADJUST(VECTOR4); + DISASSEMBLE_TYPE_ADJUST(VECTOR4I); DISASSEMBLE_TYPE_ADJUST(PLANE); DISASSEMBLE_TYPE_ADJUST(QUATERNION); DISASSEMBLE_TYPE_ADJUST(AABB); DISASSEMBLE_TYPE_ADJUST(BASIS); DISASSEMBLE_TYPE_ADJUST(TRANSFORM3D); + DISASSEMBLE_TYPE_ADJUST(PROJECTION); DISASSEMBLE_TYPE_ADJUST(COLOR); DISASSEMBLE_TYPE_ADJUST(STRING_NAME); DISASSEMBLE_TYPE_ADJUST(NODE_PATH); diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 474c8094f2..90dcfa307e 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -445,6 +445,16 @@ void GDScriptLanguage::get_public_constants(List<Pair<String, Variant>> *p_const p_constants->push_back(nan); } +void GDScriptLanguage::get_public_annotations(List<MethodInfo> *p_annotations) const { + GDScriptParser parser; + List<MethodInfo> annotations; + parser.get_annotation_list(&annotations); + + for (const MethodInfo &E : annotations) { + p_annotations->push_back(E); + } +} + String GDScriptLanguage::make_function(const String &p_class, const String &p_name, const PackedStringArray &p_args) const { #ifdef TOOLS_ENABLED bool th = EditorSettings::get_singleton()->get_setting("text_editor/completion/add_type_hints"); @@ -569,7 +579,7 @@ static int _get_enum_constant_location(StringName p_class, StringName p_enum_con // END LOCATION METHODS static String _get_visual_datatype(const PropertyInfo &p_info, bool p_is_arg = true) { - if (p_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { + if (p_info.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) { String enum_name = p_info.class_name; if (!enum_name.contains(".")) { return enum_name; @@ -950,6 +960,8 @@ static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class, } option = ScriptLanguage::CodeCompletionOption(member.signal->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_SIGNAL, location); break; + case GDScriptParser::ClassNode::Member::GROUP: + break; // No-op, but silences warnings. case GDScriptParser::ClassNode::Member::UNDEFINED: break; } @@ -1292,7 +1304,7 @@ static GDScriptCompletionIdentifier _type_from_property(const PropertyInfo &p_pr return ci; } - if (p_property.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { + if (p_property.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) { ci.enumeration = p_property.class_name; } @@ -1843,7 +1855,7 @@ static bool _guess_identifier_type(GDScriptParser::CompletionContext &p_context, while (suite) { for (int i = 0; i < suite->statements.size(); i++) { - if (suite->statements[i]->start_line > p_context.current_line) { + if (suite->statements[i]->end_line >= p_context.current_line) { break; } @@ -1891,7 +1903,7 @@ static bool _guess_identifier_type(GDScriptParser::CompletionContext &p_context, suite = suite->parent_block; } - if (last_assigned_expression && last_assign_line != p_context.current_line) { + if (last_assigned_expression && last_assign_line < p_context.current_line) { GDScriptParser::CompletionContext c = p_context; c.current_line = last_assign_line; r_type.assigned_expression = last_assigned_expression; @@ -1992,8 +2004,8 @@ static bool _guess_identifier_type(GDScriptParser::CompletionContext &p_context, return false; } - // Check autoloads. - if (ProjectSettings::get_singleton()->has_autoload(p_identifier)) { + // Check global variables (including autoloads). + if (GDScriptLanguage::get_singleton()->get_named_globals_map().has(p_identifier)) { r_type = _type_from_variant(GDScriptLanguage::get_singleton()->get_named_globals_map()[p_identifier]); return true; } @@ -2028,7 +2040,10 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext & return true; case GDScriptParser::ClassNode::Member::VARIABLE: if (!is_static) { - if (member.variable->initializer) { + if (member.variable->get_datatype().is_set() && !member.variable->get_datatype().is_variant()) { + r_type.type = member.variable->get_datatype(); + return true; + } else if (member.variable->initializer) { const GDScriptParser::ExpressionNode *init = member.variable->initializer; if (init->is_constant) { r_type.value = init->reduced_value; @@ -2050,9 +2065,6 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext & r_type.type = init->get_datatype(); return true; } - } else if (member.variable->get_datatype().is_set() && !member.variable->get_datatype().is_variant()) { - r_type.type = member.variable->get_datatype(); - return true; } } // TODO: Check assignments in constructor. @@ -2082,6 +2094,8 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext & r_type.type.kind = GDScriptParser::DataType::CLASS; r_type.type.class_type = member.m_class; return true; + case GDScriptParser::ClassNode::Member::GROUP: + return false; // No-op, but silences warnings. case GDScriptParser::ClassNode::Member::UNDEFINED: return false; // Unreachable. } @@ -2407,7 +2421,7 @@ static void _find_call_arguments(GDScriptParser::CompletionContext &p_context, c if (p_argidx < method_args) { PropertyInfo arg_info = info.arguments[p_argidx]; - if (arg_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { + if (arg_info.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) { _find_enumeration_candidates(p_context, arg_info.class_name, r_result); } } @@ -3376,6 +3390,15 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co return OK; } } break; + case GDScriptParser::COMPLETION_ANNOTATION: { + const String annotation_symbol = "@" + p_symbol; + if (parser.annotation_exists(annotation_symbol)) { + r_result.type = ScriptLanguage::LOOKUP_RESULT_CLASS_ANNOTATION; + r_result.class_name = "@GDScript"; + r_result.class_member = annotation_symbol; + return OK; + } + } break; default: { } } diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h index 3f1265679b..53c75648a0 100644 --- a/modules/gdscript/gdscript_function.h +++ b/modules/gdscript/gdscript_function.h @@ -273,11 +273,14 @@ public: OPCODE_CALL_PTRCALL_VECTOR3, OPCODE_CALL_PTRCALL_VECTOR3I, OPCODE_CALL_PTRCALL_TRANSFORM2D, + OPCODE_CALL_PTRCALL_VECTOR4, + OPCODE_CALL_PTRCALL_VECTOR4I, OPCODE_CALL_PTRCALL_PLANE, OPCODE_CALL_PTRCALL_QUATERNION, OPCODE_CALL_PTRCALL_AABB, OPCODE_CALL_PTRCALL_BASIS, OPCODE_CALL_PTRCALL_TRANSFORM3D, + OPCODE_CALL_PTRCALL_PROJECTION, OPCODE_CALL_PTRCALL_COLOR, OPCODE_CALL_PTRCALL_STRING_NAME, OPCODE_CALL_PTRCALL_NODE_PATH, @@ -363,11 +366,14 @@ public: OPCODE_TYPE_ADJUST_VECTOR3, OPCODE_TYPE_ADJUST_VECTOR3I, OPCODE_TYPE_ADJUST_TRANSFORM2D, + OPCODE_TYPE_ADJUST_VECTOR4, + OPCODE_TYPE_ADJUST_VECTOR4I, OPCODE_TYPE_ADJUST_PLANE, OPCODE_TYPE_ADJUST_QUATERNION, OPCODE_TYPE_ADJUST_AABB, OPCODE_TYPE_ADJUST_BASIS, OPCODE_TYPE_ADJUST_TRANSFORM3D, + OPCODE_TYPE_ADJUST_PROJECTION, OPCODE_TYPE_ADJUST_COLOR, OPCODE_TYPE_ADJUST_STRING_NAME, OPCODE_TYPE_ADJUST_NODE_PATH, diff --git a/modules/gdscript/gdscript_lambda_callable.h b/modules/gdscript/gdscript_lambda_callable.h index 248176e32c..1954089983 100644 --- a/modules/gdscript/gdscript_lambda_callable.h +++ b/modules/gdscript/gdscript_lambda_callable.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GDSCRIPT_LAMBDA_CALLABLE -#define GDSCRIPT_LAMBDA_CALLABLE +#ifndef GDSCRIPT_LAMBDA_CALLABLE_H +#define GDSCRIPT_LAMBDA_CALLABLE_H #include "core/object/ref_counted.h" #include "core/templates/vector.h" @@ -87,4 +87,4 @@ public: virtual ~GDScriptLambdaSelfCallable() = default; }; -#endif // GDSCRIPT_LAMBDA_CALLABLE +#endif // GDSCRIPT_LAMBDA_CALLABLE_H diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index ca430b0f72..e8fa2981ba 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -60,11 +60,14 @@ Variant::Type GDScriptParser::get_builtin_type(const StringName &p_type) { builtin_types["Transform2D"] = Variant::TRANSFORM2D; builtin_types["Vector3"] = Variant::VECTOR3; builtin_types["Vector3i"] = Variant::VECTOR3I; + builtin_types["Vector4"] = Variant::VECTOR4; + builtin_types["Vector4i"] = Variant::VECTOR4I; builtin_types["AABB"] = Variant::AABB; builtin_types["Plane"] = Variant::PLANE; builtin_types["Quaternion"] = Variant::QUATERNION; builtin_types["Basis"] = Variant::BASIS; builtin_types["Transform3D"] = Variant::TRANSFORM3D; + builtin_types["Projection"] = Variant::PROJECTION; builtin_types["Color"] = Variant::COLOR; builtin_types["RID"] = Variant::RID; builtin_types["Object"] = Variant::OBJECT; @@ -105,6 +108,10 @@ void GDScriptParser::get_annotation_list(List<MethodInfo> *r_annotations) const } } +bool GDScriptParser::annotation_exists(const String &p_annotation_name) const { + return valid_annotations.has(p_annotation_name); +} + GDScriptParser::GDScriptParser() { // Register valid annotations. // TODO: Should this be static? @@ -113,27 +120,32 @@ GDScriptParser::GDScriptParser() { register_annotation(MethodInfo("@onready"), AnnotationInfo::VARIABLE, &GDScriptParser::onready_annotation); // Export annotations. register_annotation(MethodInfo("@export"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_NONE, Variant::NIL>); - register_annotation(MethodInfo("@export_enum", PropertyInfo(Variant::STRING, "names")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_ENUM, Variant::INT>, 0, true); - register_annotation(MethodInfo("@export_file", PropertyInfo(Variant::STRING, "filter")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_FILE, Variant::STRING>, 1, true); + register_annotation(MethodInfo("@export_enum", PropertyInfo(Variant::STRING, "names")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_ENUM, Variant::INT>, varray(), true); + register_annotation(MethodInfo("@export_file", PropertyInfo(Variant::STRING, "filter")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_FILE, Variant::STRING>, varray(""), true); register_annotation(MethodInfo("@export_dir"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_DIR, Variant::STRING>); - register_annotation(MethodInfo("@export_global_file", PropertyInfo(Variant::STRING, "filter")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_GLOBAL_FILE, Variant::STRING>, 1, true); + register_annotation(MethodInfo("@export_global_file", PropertyInfo(Variant::STRING, "filter")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_GLOBAL_FILE, Variant::STRING>, varray(""), true); register_annotation(MethodInfo("@export_global_dir"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_GLOBAL_DIR, Variant::STRING>); register_annotation(MethodInfo("@export_multiline"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_MULTILINE_TEXT, Variant::STRING>); register_annotation(MethodInfo("@export_placeholder"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_PLACEHOLDER_TEXT, Variant::STRING>); - register_annotation(MethodInfo("@export_range", PropertyInfo(Variant::FLOAT, "min"), PropertyInfo(Variant::FLOAT, "max"), PropertyInfo(Variant::FLOAT, "step"), PropertyInfo(Variant::STRING, "slider1"), PropertyInfo(Variant::STRING, "slider2"), PropertyInfo(Variant::STRING, "slider3")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_RANGE, Variant::FLOAT>, 4); - register_annotation(MethodInfo("@export_exp_easing", PropertyInfo(Variant::STRING, "hint1"), PropertyInfo(Variant::STRING, "hint2")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_EXP_EASING, Variant::FLOAT>, 2); + register_annotation(MethodInfo("@export_range", PropertyInfo(Variant::FLOAT, "min"), PropertyInfo(Variant::FLOAT, "max"), PropertyInfo(Variant::FLOAT, "step"), PropertyInfo(Variant::STRING, "extra_hints")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_RANGE, Variant::FLOAT>, varray(1.0, ""), true); + register_annotation(MethodInfo("@export_exp_easing", PropertyInfo(Variant::STRING, "hints")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_EXP_EASING, Variant::FLOAT>, varray(""), true); register_annotation(MethodInfo("@export_color_no_alpha"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_COLOR_NO_ALPHA, Variant::COLOR>); - register_annotation(MethodInfo("@export_node_path", PropertyInfo(Variant::STRING, "type")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_NODE_PATH_VALID_TYPES, Variant::NODE_PATH>, 1, true); - register_annotation(MethodInfo("@export_flags", PropertyInfo(Variant::STRING, "names")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_FLAGS, Variant::INT>, 0, true); + register_annotation(MethodInfo("@export_node_path", PropertyInfo(Variant::STRING, "type")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_NODE_PATH_VALID_TYPES, Variant::NODE_PATH>, varray(""), true); + register_annotation(MethodInfo("@export_flags", PropertyInfo(Variant::STRING, "names")), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_FLAGS, Variant::INT>, varray(), true); register_annotation(MethodInfo("@export_flags_2d_render"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_2D_RENDER, Variant::INT>); register_annotation(MethodInfo("@export_flags_2d_physics"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_2D_PHYSICS, Variant::INT>); register_annotation(MethodInfo("@export_flags_2d_navigation"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_2D_NAVIGATION, Variant::INT>); register_annotation(MethodInfo("@export_flags_3d_render"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_RENDER, Variant::INT>); register_annotation(MethodInfo("@export_flags_3d_physics"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_PHYSICS, Variant::INT>); register_annotation(MethodInfo("@export_flags_3d_navigation"), AnnotationInfo::VARIABLE, &GDScriptParser::export_annotations<PROPERTY_HINT_LAYERS_3D_NAVIGATION, Variant::INT>); - register_annotation(MethodInfo("@warning_ignore", PropertyInfo(Variant::STRING, "warning")), AnnotationInfo::CLASS | AnnotationInfo::VARIABLE | AnnotationInfo::SIGNAL | AnnotationInfo::CONSTANT | AnnotationInfo::FUNCTION | AnnotationInfo::STATEMENT, &GDScriptParser::warning_annotations, 0, true); + // Export grouping annotations. + register_annotation(MethodInfo("@export_category", PropertyInfo(Variant::STRING, "name")), AnnotationInfo::STANDALONE, &GDScriptParser::export_group_annotations<PROPERTY_USAGE_CATEGORY>); + register_annotation(MethodInfo("@export_group", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::STRING, "prefix")), AnnotationInfo::STANDALONE, &GDScriptParser::export_group_annotations<PROPERTY_USAGE_GROUP>, varray("")); + register_annotation(MethodInfo("@export_subgroup", PropertyInfo(Variant::STRING, "name"), PropertyInfo(Variant::STRING, "prefix")), AnnotationInfo::STANDALONE, &GDScriptParser::export_group_annotations<PROPERTY_USAGE_SUBGROUP>, varray("")); + // Warning annotations. + register_annotation(MethodInfo("@warning_ignore", PropertyInfo(Variant::STRING, "warning")), AnnotationInfo::CLASS | AnnotationInfo::VARIABLE | AnnotationInfo::SIGNAL | AnnotationInfo::CONSTANT | AnnotationInfo::FUNCTION | AnnotationInfo::STATEMENT, &GDScriptParser::warning_annotations, varray(), true); // Networking. - register_annotation(MethodInfo("@rpc", PropertyInfo(Variant::STRING, "mode"), PropertyInfo(Variant::STRING, "sync"), PropertyInfo(Variant::STRING, "transfer_mode"), PropertyInfo(Variant::INT, "transfer_channel")), AnnotationInfo::FUNCTION, &GDScriptParser::network_annotations<Multiplayer::RPC_MODE_AUTHORITY>, 4, true); + register_annotation(MethodInfo("@rpc", PropertyInfo(Variant::STRING, "mode"), PropertyInfo(Variant::STRING, "sync"), PropertyInfo(Variant::STRING, "transfer_mode"), PropertyInfo(Variant::INT, "transfer_channel")), AnnotationInfo::FUNCTION, &GDScriptParser::network_annotations<Multiplayer::RPC_MODE_AUTHORITY>, varray("", "", "", 0), true); } GDScriptParser::~GDScriptParser() { @@ -153,6 +165,7 @@ void GDScriptParser::clear() { for_completion = false; errors.clear(); multiline_stack.clear(); + nodes_in_progress.clear(); } void GDScriptParser::push_error(const String &p_message, const Node *p_origin) { @@ -404,6 +417,9 @@ GDScriptTokenizer::Token GDScriptParser::advance() { push_error(current.literal); current = tokenizer.scan(); } + for (Node *n : nodes_in_progress) { + update_extents(n); + } return previous; } @@ -519,9 +535,13 @@ void GDScriptParser::parse_program() { head = alloc_node<ClassNode>(); current_class = head; + // If we happen to parse an annotation before extends or class_name keywords, track it. + // @tool is allowed, but others should fail. + AnnotationNode *premature_annotation = nullptr; + if (match(GDScriptTokenizer::Token::ANNOTATION)) { - // Check for @tool annotation. - AnnotationNode *annotation = parse_annotation(AnnotationInfo::SCRIPT | AnnotationInfo::CLASS_LEVEL); + // Check for @tool, script-level, or standalone annotation. + AnnotationNode *annotation = parse_annotation(AnnotationInfo::SCRIPT | AnnotationInfo::STANDALONE | AnnotationInfo::CLASS_LEVEL); if (annotation != nullptr) { if (annotation->name == SNAME("@tool")) { // TODO: don't allow @tool anywhere else. (Should all script annotations be the first thing?). @@ -531,7 +551,14 @@ void GDScriptParser::parse_program() { } // @tool annotation has no specific target. annotation->apply(this, nullptr); + } else if (annotation->applies_to(AnnotationInfo::SCRIPT | AnnotationInfo::STANDALONE)) { + premature_annotation = annotation; + if (previous.type != GDScriptTokenizer::Token::NEWLINE) { + push_error(R"(Expected newline after a standalone annotation.)"); + } + annotation->apply(this, head); } else { + premature_annotation = annotation; annotation_stack.push_back(annotation); } } @@ -541,8 +568,8 @@ void GDScriptParser::parse_program() { // Order here doesn't matter, but there should be only one of each at most. switch (current.type) { case GDScriptTokenizer::Token::CLASS_NAME: - if (!annotation_stack.is_empty()) { - push_error(R"("class_name" should be used before annotations.)"); + if (premature_annotation != nullptr) { + push_error(R"("class_name" should be used before annotations (except @tool).)"); } advance(); if (head->identifier != nullptr) { @@ -552,8 +579,8 @@ void GDScriptParser::parse_program() { } break; case GDScriptTokenizer::Token::EXTENDS: - if (!annotation_stack.is_empty()) { - push_error(R"("extends" should be used before annotations.)"); + if (premature_annotation != nullptr) { + push_error(R"("extends" should be used before annotations (except @tool).)"); } advance(); if (head->extends_used) { @@ -574,12 +601,12 @@ void GDScriptParser::parse_program() { } if (match(GDScriptTokenizer::Token::ANNOTATION)) { - // Check for @icon annotation. - AnnotationNode *annotation = parse_annotation(AnnotationInfo::SCRIPT | AnnotationInfo::CLASS_LEVEL); + // Check for a script-level, or standalone annotation. + AnnotationNode *annotation = parse_annotation(AnnotationInfo::SCRIPT | AnnotationInfo::STANDALONE | AnnotationInfo::CLASS_LEVEL); if (annotation != nullptr) { - if (annotation->name == SNAME("@icon")) { + if (annotation->applies_to(AnnotationInfo::SCRIPT | AnnotationInfo::STANDALONE)) { if (previous.type != GDScriptTokenizer::Token::NEWLINE) { - push_error(R"(Expected newline after "@icon" annotation.)"); + push_error(R"(Expected newline after a standalone annotation.)"); } annotation->apply(this, head); } else { @@ -589,6 +616,7 @@ void GDScriptParser::parse_program() { } parse_class_body(true); + complete_extents(head); #ifdef TOOLS_ENABLED for (const KeyValue<int, GDScriptTokenizer::CommentData> &E : tokenizer.get_comments()) { @@ -629,6 +657,7 @@ GDScriptParser::ClassNode *GDScriptParser::parse_class() { if (multiline && !consume(GDScriptTokenizer::Token::INDENT, R"(Expected indented block after class declaration.)")) { current_class = previous_class; + complete_extents(n_class); return n_class; } @@ -641,6 +670,7 @@ GDScriptParser::ClassNode *GDScriptParser::parse_class() { } parse_class_body(multiline); + complete_extents(n_class); if (multiline) { consume(GDScriptTokenizer::Token::DEDENT, R"(Missing unindent at the end of the class body.)"); @@ -807,9 +837,18 @@ void GDScriptParser::parse_class_body(bool p_is_multiline) { break; case GDScriptTokenizer::Token::ANNOTATION: { advance(); - AnnotationNode *annotation = parse_annotation(AnnotationInfo::CLASS_LEVEL); + + // Check for class-level annotations. + AnnotationNode *annotation = parse_annotation(AnnotationInfo::STANDALONE | AnnotationInfo::CLASS_LEVEL); if (annotation != nullptr) { - annotation_stack.push_back(annotation); + if (annotation->applies_to(AnnotationInfo::STANDALONE)) { + if (previous.type != GDScriptTokenizer::Token::NEWLINE) { + push_error(R"(Expected newline after a standalone annotation.)"); + } + annotation->apply(this, head); + } else { + annotation_stack.push_back(annotation); + } } break; } @@ -841,11 +880,13 @@ GDScriptParser::VariableNode *GDScriptParser::parse_variable() { } GDScriptParser::VariableNode *GDScriptParser::parse_variable(bool p_allow_property) { + VariableNode *variable = alloc_node<VariableNode>(); + if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected variable name after "var".)")) { + complete_extents(variable); return nullptr; } - VariableNode *variable = alloc_node<VariableNode>(); variable->identifier = parse_identifier(); variable->export_info.name = variable->identifier->name; @@ -853,10 +894,10 @@ GDScriptParser::VariableNode *GDScriptParser::parse_variable(bool p_allow_proper if (check(GDScriptTokenizer::Token::NEWLINE)) { if (p_allow_property) { advance(); - return parse_property(variable, true); } else { push_error(R"(Expected type after ":")"); + complete_extents(variable); return nullptr; } } else if (check((GDScriptTokenizer::Token::EQUAL))) { @@ -895,6 +936,7 @@ GDScriptParser::VariableNode *GDScriptParser::parse_variable(bool p_allow_proper } } + complete_extents(variable); end_statement("variable declaration"); return variable; @@ -903,6 +945,7 @@ GDScriptParser::VariableNode *GDScriptParser::parse_variable(bool p_allow_proper GDScriptParser::VariableNode *GDScriptParser::parse_property(VariableNode *p_variable, bool p_need_indent) { if (p_need_indent) { if (!consume(GDScriptTokenizer::Token::INDENT, R"(Expected indented block for property after ":".)")) { + complete_extents(p_variable); return nullptr; } } @@ -912,6 +955,7 @@ GDScriptParser::VariableNode *GDScriptParser::parse_property(VariableNode *p_var make_completion_context(COMPLETION_PROPERTY_DECLARATION, property); if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected "get" or "set" for property declaration.)")) { + complete_extents(p_variable); return nullptr; } @@ -968,6 +1012,7 @@ GDScriptParser::VariableNode *GDScriptParser::parse_property(VariableNode *p_var } function = parse_identifier(); } + complete_extents(p_variable); if (p_variable->property == VariableNode::PROP_SETGET) { end_statement("property declaration"); @@ -982,37 +1027,37 @@ GDScriptParser::VariableNode *GDScriptParser::parse_property(VariableNode *p_var void GDScriptParser::parse_property_setter(VariableNode *p_variable) { switch (p_variable->property) { case VariableNode::PROP_INLINE: { - consume(GDScriptTokenizer::Token::PARENTHESIS_OPEN, R"(Expected "(" after "set".)"); - if (consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected parameter name after "(".)")) { - p_variable->setter_parameter = parse_identifier(); - } - consume(GDScriptTokenizer::Token::PARENTHESIS_CLOSE, R"*(Expected ")" after parameter name.)*"); - consume(GDScriptTokenizer::Token::COLON, R"*(Expected ":" after ")".)*"); - + FunctionNode *function = alloc_node<FunctionNode>(); IdentifierNode *identifier = alloc_node<IdentifierNode>(); + complete_extents(identifier); identifier->name = "@" + p_variable->identifier->name + "_setter"; - - FunctionNode *function = alloc_node<FunctionNode>(); function->identifier = identifier; - FunctionNode *previous_function = current_function; - current_function = function; + consume(GDScriptTokenizer::Token::PARENTHESIS_OPEN, R"(Expected "(" after "set".)"); ParameterNode *parameter = alloc_node<ParameterNode>(); - parameter->identifier = p_variable->setter_parameter; - - if (parameter->identifier != nullptr) { + if (consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected parameter name after "(".)")) { + reset_extents(parameter, previous); + p_variable->setter_parameter = parse_identifier(); + parameter->identifier = p_variable->setter_parameter; function->parameters_indices[parameter->identifier->name] = 0; function->parameters.push_back(parameter); + } + complete_extents(parameter); + consume(GDScriptTokenizer::Token::PARENTHESIS_CLOSE, R"*(Expected ")" after parameter name.)*"); + consume(GDScriptTokenizer::Token::COLON, R"*(Expected ":" after ")".)*"); + + FunctionNode *previous_function = current_function; + current_function = function; + if (p_variable->setter_parameter != nullptr) { SuiteNode *body = alloc_node<SuiteNode>(); body->add_local(parameter, function); - function->body = parse_suite("setter declaration", body); p_variable->setter = function; } - current_function = previous_function; + complete_extents(function); break; } case VariableNode::PROP_SETGET: @@ -1030,12 +1075,13 @@ void GDScriptParser::parse_property_setter(VariableNode *p_variable) { void GDScriptParser::parse_property_getter(VariableNode *p_variable) { switch (p_variable->property) { case VariableNode::PROP_INLINE: { + FunctionNode *function = alloc_node<FunctionNode>(); + consume(GDScriptTokenizer::Token::COLON, R"(Expected ":" after "get".)"); IdentifierNode *identifier = alloc_node<IdentifierNode>(); + complete_extents(identifier); identifier->name = "@" + p_variable->identifier->name + "_getter"; - - FunctionNode *function = alloc_node<FunctionNode>(); function->identifier = identifier; FunctionNode *previous_function = current_function; @@ -1043,9 +1089,10 @@ void GDScriptParser::parse_property_getter(VariableNode *p_variable) { SuiteNode *body = alloc_node<SuiteNode>(); function->body = parse_suite("getter declaration", body); - p_variable->getter = function; + current_function = previous_function; + complete_extents(function); break; } case VariableNode::PROP_SETGET: @@ -1061,11 +1108,12 @@ void GDScriptParser::parse_property_getter(VariableNode *p_variable) { } GDScriptParser::ConstantNode *GDScriptParser::parse_constant() { + ConstantNode *constant = alloc_node<ConstantNode>(); + if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected constant name after "const".)")) { return nullptr; } - ConstantNode *constant = alloc_node<ConstantNode>(); constant->identifier = parse_identifier(); if (match(GDScriptTokenizer::Token::COLON)) { @@ -1084,12 +1132,15 @@ GDScriptParser::ConstantNode *GDScriptParser::parse_constant() { if (constant->initializer == nullptr) { push_error(R"(Expected initializer expression for constant.)"); + complete_extents(constant); return nullptr; } } else { + complete_extents(constant); return nullptr; } + complete_extents(constant); end_statement("constant declaration"); return constant; @@ -1119,15 +1170,18 @@ GDScriptParser::ParameterNode *GDScriptParser::parse_parameter() { parameter->default_value = parse_expression(false); } + complete_extents(parameter); return parameter; } GDScriptParser::SignalNode *GDScriptParser::parse_signal() { + SignalNode *signal = alloc_node<SignalNode>(); + if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected signal name after "signal".)")) { + complete_extents(signal); return nullptr; } - SignalNode *signal = alloc_node<SignalNode>(); signal->identifier = parse_identifier(); if (check(GDScriptTokenizer::Token::PARENTHESIS_OPEN)) { @@ -1159,6 +1213,7 @@ GDScriptParser::SignalNode *GDScriptParser::parse_signal() { consume(GDScriptTokenizer::Token::PARENTHESIS_CLOSE, R"*(Expected closing ")" after signal parameters.)*"); } + complete_extents(signal); end_statement("signal declaration"); return signal; @@ -1270,6 +1325,7 @@ GDScriptParser::EnumNode *GDScriptParser::parse_enum() { } #endif // TOOLS_ENABLED + complete_extents(enum_node); end_statement("enum"); return enum_node; @@ -1321,19 +1377,22 @@ void GDScriptParser::parse_function_signature(FunctionNode *p_function, SuiteNod } GDScriptParser::FunctionNode *GDScriptParser::parse_function() { + FunctionNode *function = alloc_node<FunctionNode>(); + bool _static = false; if (previous.type == GDScriptTokenizer::Token::STATIC) { // TODO: Improve message if user uses "static" with "var" or "const" if (!consume(GDScriptTokenizer::Token::FUNC, R"(Expected "func" after "static".)")) { + complete_extents(function); return nullptr; } _static = true; } - FunctionNode *function = alloc_node<FunctionNode>(); make_completion_context(COMPLETION_OVERRIDE_METHOD, function); if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected function name after "func".)")) { + complete_extents(function); return nullptr; } @@ -1355,6 +1414,7 @@ GDScriptParser::FunctionNode *GDScriptParser::parse_function() { function->body = parse_suite("function declaration", body); current_function = previous_function; + complete_extents(function); return function; } @@ -1402,6 +1462,7 @@ GDScriptParser::AnnotationNode *GDScriptParser::parse_annotation(uint32_t p_vali } pop_completion_call(); } + complete_extents(annotation); match(GDScriptTokenizer::Token::NEWLINE); // Newline after annotation is optional. @@ -1420,12 +1481,12 @@ void GDScriptParser::clear_unused_annotations() { annotation_stack.clear(); } -bool GDScriptParser::register_annotation(const MethodInfo &p_info, uint32_t p_target_kinds, AnnotationAction p_apply, int p_optional_arguments, bool p_is_vararg) { +bool GDScriptParser::register_annotation(const MethodInfo &p_info, uint32_t p_target_kinds, AnnotationAction p_apply, const Vector<Variant> &p_default_arguments, bool p_is_vararg) { ERR_FAIL_COND_V_MSG(valid_annotations.has(p_info.name), false, vformat(R"(Annotation "%s" already registered.)", p_info.name)); AnnotationInfo new_annotation; new_annotation.info = p_info; - new_annotation.info.default_arguments.resize(p_optional_arguments); + new_annotation.info.default_arguments = p_default_arguments; if (p_is_vararg) { new_annotation.info.flags |= METHOD_FLAG_VARARG; } @@ -1451,9 +1512,11 @@ GDScriptParser::SuiteNode *GDScriptParser::parse_suite(const String &p_context, if (multiline) { if (!consume(GDScriptTokenizer::Token::INDENT, vformat(R"(Expected indented block after %s.)", p_context))) { current_suite = suite->parent_block; + complete_extents(suite); return suite; } } + reset_extents(suite, current); int error_count = 0; @@ -1503,6 +1566,8 @@ GDScriptParser::SuiteNode *GDScriptParser::parse_suite(const String &p_context, } while ((multiline || previous.type == GDScriptTokenizer::Token::SEMICOLON) && !check(GDScriptTokenizer::Token::DEDENT) && !lambda_ended && !is_at_end()); + complete_extents(suite); + if (multiline) { if (!lambda_ended) { consume(GDScriptTokenizer::Token::DEDENT, vformat(R"(Missing unindent at the end of %s.)", p_context)); @@ -1533,6 +1598,7 @@ GDScriptParser::Node *GDScriptParser::parse_statement() { case GDScriptTokenizer::Token::PASS: advance(); result = alloc_node<PassNode>(); + complete_extents(result); end_statement(R"("pass")"); break; case GDScriptTokenizer::Token::VAR: @@ -1580,6 +1646,7 @@ GDScriptParser::Node *GDScriptParser::parse_statement() { // If this fails the expression will be nullptr, but that's the same as no return, so it's fine. n_return->return_value = parse_expression(false); } + complete_extents(n_return); result = n_return; current_suite->has_return = true; @@ -1590,6 +1657,7 @@ GDScriptParser::Node *GDScriptParser::parse_statement() { case GDScriptTokenizer::Token::BREAKPOINT: advance(); result = alloc_node<BreakpointNode>(); + complete_extents(result); end_statement(R"("breakpoint")"); break; case GDScriptTokenizer::Token::ASSERT: @@ -1615,10 +1683,12 @@ GDScriptParser::Node *GDScriptParser::parse_statement() { lambda_ended = true; has_ended_lambda = true; } else { + advance(); push_error(vformat(R"(Expected statement, found "%s" instead.)", previous.get_name())); } + } else { + end_statement("expression"); } - end_statement("expression"); lambda_ended = lambda_ended || has_ended_lambda; result = expression; @@ -1681,6 +1751,7 @@ GDScriptParser::AssertNode *GDScriptParser::parse_assert() { assert->condition = parse_expression(false); if (assert->condition == nullptr) { push_error("Expected expression to assert."); + complete_extents(assert); return nullptr; } @@ -1689,12 +1760,14 @@ GDScriptParser::AssertNode *GDScriptParser::parse_assert() { assert->message = parse_expression(false); if (assert->message == nullptr) { push_error(R"(Expected error message for assert after ",".)"); + complete_extents(assert); return nullptr; } } consume(GDScriptTokenizer::Token::PARENTHESIS_CLOSE, R"*(Expected ")" after assert expression.)*"); + complete_extents(assert); end_statement(R"("assert")"); return assert; @@ -1704,8 +1777,10 @@ GDScriptParser::BreakNode *GDScriptParser::parse_break() { if (!can_break) { push_error(R"(Cannot use "break" outside of a loop.)"); } + BreakNode *break_node = alloc_node<BreakNode>(); + complete_extents(break_node); end_statement(R"("break")"); - return alloc_node<BreakNode>(); + return break_node; } GDScriptParser::ContinueNode *GDScriptParser::parse_continue() { @@ -1713,9 +1788,10 @@ GDScriptParser::ContinueNode *GDScriptParser::parse_continue() { push_error(R"(Cannot use "continue" outside of a loop or pattern matching block.)"); } current_suite->has_continue = true; - end_statement(R"("continue")"); ContinueNode *cont = alloc_node<ContinueNode>(); cont->is_for_match = is_continue_match; + complete_extents(cont); + end_statement(R"("continue")"); return cont; } @@ -1748,11 +1824,16 @@ GDScriptParser::ForNode *GDScriptParser::parse_for() { SuiteNode *suite = alloc_node<SuiteNode>(); if (n_for->variable) { + const SuiteNode::Local &local = current_suite->get_local(n_for->variable->name); + if (local.type != SuiteNode::Local::UNDEFINED) { + push_error(vformat(R"(There is already a %s named "%s" declared in this scope.)", local.get_name(), n_for->variable->name), n_for->variable); + } suite->add_local(SuiteNode::Local(n_for->variable, current_function)); } suite->parent_for = n_for; n_for->loop = parse_suite(R"("for" block)", suite); + complete_extents(n_for); // Reset break/continue state. can_break = could_break; @@ -1780,15 +1861,16 @@ GDScriptParser::IfNode *GDScriptParser::parse_if(const String &p_token) { } if (match(GDScriptTokenizer::Token::ELIF)) { - IfNode *elif = parse_if("elif"); - SuiteNode *else_block = alloc_node<SuiteNode>(); + IfNode *elif = parse_if("elif"); else_block->statements.push_back(elif); + complete_extents(else_block); n_if->false_block = else_block; } else if (match(GDScriptTokenizer::Token::ELSE)) { consume(GDScriptTokenizer::Token::COLON, R"(Expected ":" after "else".)"); n_if->false_block = parse_suite(R"("else" block)"); } + complete_extents(n_if); if (n_if->false_block != nullptr && n_if->false_block->has_return && n_if->true_block->has_return) { current_suite->has_return = true; @@ -1812,6 +1894,7 @@ GDScriptParser::MatchNode *GDScriptParser::parse_match() { consume(GDScriptTokenizer::Token::NEWLINE, R"(Expected a newline after "match" statement.)"); if (!consume(GDScriptTokenizer::Token::INDENT, R"(Expected an indented block after "match" statement.)")) { + complete_extents(match); return match; } @@ -1829,7 +1912,7 @@ GDScriptParser::MatchNode *GDScriptParser::parse_match() { } #ifdef DEBUG_ENABLED - if (have_wildcard_without_continue) { + if (have_wildcard_without_continue && !branch->patterns.is_empty()) { push_warning(branch->patterns[0], GDScriptWarning::UNREACHABLE_PATTERN); } @@ -1845,6 +1928,7 @@ GDScriptParser::MatchNode *GDScriptParser::parse_match() { #endif match->branches.push_back(branch); } + complete_extents(match); consume(GDScriptTokenizer::Token::DEDENT, R"(Expected an indented block after "match" statement.)"); @@ -1859,6 +1943,7 @@ GDScriptParser::MatchNode *GDScriptParser::parse_match() { GDScriptParser::MatchBranchNode *GDScriptParser::parse_match_branch() { MatchBranchNode *branch = alloc_node<MatchBranchNode>(); + reset_extents(branch, current); bool has_bind = false; @@ -1886,6 +1971,7 @@ GDScriptParser::MatchBranchNode *GDScriptParser::parse_match_branch() { } if (!consume(GDScriptTokenizer::Token::COLON, R"(Expected ":" after "match" patterns.)")) { + complete_extents(branch); return nullptr; } @@ -1906,6 +1992,7 @@ GDScriptParser::MatchBranchNode *GDScriptParser::parse_match_branch() { } branch->block = parse_suite("match pattern block", suite); + complete_extents(branch); // Restore continue state. can_continue = could_continue; @@ -1916,12 +2003,14 @@ GDScriptParser::MatchBranchNode *GDScriptParser::parse_match_branch() { GDScriptParser::PatternNode *GDScriptParser::parse_match_pattern(PatternNode *p_root_pattern) { PatternNode *pattern = alloc_node<PatternNode>(); + reset_extents(pattern, current); switch (current.type) { case GDScriptTokenizer::Token::VAR: { // Bind. advance(); if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected bind name after "var".)")) { + complete_extents(pattern); return nullptr; } pattern->pattern_type = PatternNode::PT_BIND; @@ -1932,12 +2021,14 @@ GDScriptParser::PatternNode *GDScriptParser::parse_match_pattern(PatternNode *p_ if (p_root_pattern != nullptr) { if (p_root_pattern->has_bind(pattern->bind->name)) { push_error(vformat(R"(Bind variable name "%s" was already used in this pattern.)", pattern->bind->name)); + complete_extents(pattern); return nullptr; } } if (current_suite->has_local(pattern->bind->name)) { push_error(vformat(R"(There's already a %s named "%s" in this scope.)", current_suite->get_local(pattern->bind->name).get_name(), pattern->bind->name)); + complete_extents(pattern); return nullptr; } @@ -1990,6 +2081,7 @@ GDScriptParser::PatternNode *GDScriptParser::parse_match_pattern(PatternNode *p_ push_error(R"(The ".." pattern must be the last element in the pattern dictionary.)"); } else { PatternNode *sub_pattern = alloc_node<PatternNode>(); + complete_extents(sub_pattern); sub_pattern->pattern_type = PatternNode::PT_REST; pattern->dictionary.push_back({ nullptr, sub_pattern }); pattern->rest_used = true; @@ -2038,6 +2130,7 @@ GDScriptParser::PatternNode *GDScriptParser::parse_match_pattern(PatternNode *p_ break; } } + complete_extents(pattern); return pattern; } @@ -2071,6 +2164,7 @@ GDScriptParser::WhileNode *GDScriptParser::parse_while() { is_continue_match = false; n_while->loop = parse_suite(R"("while" block)"); + complete_extents(n_while); // Reset break/continue state. can_break = could_break; @@ -2143,6 +2237,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_identifier(ExpressionNode ERR_FAIL_V_MSG(nullptr, "Parser bug: parsing literal node without literal token."); } IdentifierNode *identifier = alloc_node<IdentifierNode>(); + complete_extents(identifier); identifier->name = previous.get_identifier(); if (current_suite != nullptr && current_suite->has_local(identifier->name)) { @@ -2194,6 +2289,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_literal(ExpressionNode *p_ } LiteralNode *literal = alloc_node<LiteralNode>(); + complete_extents(literal); literal->value = previous.literal; return literal; } @@ -2203,6 +2299,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_self(ExpressionNode *p_pre push_error(R"(Cannot use "self" inside a static function.)"); } SelfNode *self = alloc_node<SelfNode>(); + complete_extents(self); self->current_class = current_class; return self; } @@ -2210,6 +2307,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_self(ExpressionNode *p_pre GDScriptParser::ExpressionNode *GDScriptParser::parse_builtin_constant(ExpressionNode *p_previous_operand, bool p_can_assign) { GDScriptTokenizer::Token::Type op_type = previous.type; LiteralNode *constant = alloc_node<LiteralNode>(); + complete_extents(constant); switch (op_type) { case GDScriptTokenizer::Token::CONST_PI: @@ -2270,30 +2368,38 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_unary_operator(ExpressionN } break; default: + complete_extents(operation); return nullptr; // Unreachable. } + complete_extents(operation); return operation; } GDScriptParser::ExpressionNode *GDScriptParser::parse_binary_not_in_operator(ExpressionNode *p_previous_operand, bool p_can_assign) { // check that NOT is followed by IN by consuming it before calling parse_binary_operator which will only receive a plain IN + UnaryOpNode *operation = alloc_node<UnaryOpNode>(); + reset_extents(operation, p_previous_operand); + update_extents(operation); consume(GDScriptTokenizer::Token::IN, R"(Expected "in" after "not" in content-test operator.)"); ExpressionNode *in_operation = parse_binary_operator(p_previous_operand, p_can_assign); - UnaryOpNode *operation = alloc_node<UnaryOpNode>(); operation->operation = UnaryOpNode::OP_LOGIC_NOT; operation->variant_op = Variant::OP_NOT; operation->operand = in_operation; + complete_extents(operation); return operation; } GDScriptParser::ExpressionNode *GDScriptParser::parse_binary_operator(ExpressionNode *p_previous_operand, bool p_can_assign) { GDScriptTokenizer::Token op = previous; BinaryOpNode *operation = alloc_node<BinaryOpNode>(); + reset_extents(operation, p_previous_operand); + update_extents(operation); Precedence precedence = (Precedence)(get_rule(op.type)->precedence + 1); operation->left_operand = p_previous_operand; operation->right_operand = parse_precedence(precedence, false); + complete_extents(operation); if (operation->right_operand == nullptr) { push_error(vformat(R"(Expected expression after "%s" operator.")", op.get_name())); @@ -2396,8 +2502,10 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_binary_operator(Expression GDScriptParser::ExpressionNode *GDScriptParser::parse_ternary_operator(ExpressionNode *p_previous_operand, bool p_can_assign) { // Only one ternary operation exists, so no abstraction here. TernaryOpNode *operation = alloc_node<TernaryOpNode>(); - operation->true_expr = p_previous_operand; + reset_extents(operation, p_previous_operand); + update_extents(operation); + operation->true_expr = p_previous_operand; operation->condition = parse_precedence(PREC_TERNARY, false); if (operation->condition == nullptr) { @@ -2412,6 +2520,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_ternary_operator(Expressio push_error(R"(Expected expression after "else".)"); } + complete_extents(operation); return operation; } @@ -2464,6 +2573,9 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_assignment(ExpressionNode } AssignmentNode *assignment = alloc_node<AssignmentNode>(); + reset_extents(assignment, p_previous_operand); + update_extents(assignment); + make_completion_context(COMPLETION_ASSIGN, assignment); #ifdef DEBUG_ENABLED bool has_operator = true; @@ -2528,6 +2640,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_assignment(ExpressionNode if (assignment->assigned_value == nullptr) { push_error(R"(Expected an expression after "=".)"); } + complete_extents(assignment); #ifdef DEBUG_ENABLED if (source_variable != nullptr) { @@ -2549,6 +2662,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_await(ExpressionNode *p_pr push_error(R"(Expected signal or coroutine after "await".)"); } await->to_await = element; + complete_extents(await); if (current_function) { // Might be null in a getter or setter. current_function->is_coroutine = true; @@ -2577,6 +2691,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_array(ExpressionNode *p_pr } pop_multiline(); consume(GDScriptTokenizer::Token::BRACKET_CLOSE, R"(Expected closing "]" after array elements.)"); + complete_extents(array); return array; } @@ -2668,6 +2783,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_dictionary(ExpressionNode } pop_multiline(); consume(GDScriptTokenizer::Token::BRACE_CLOSE, R"(Expected closing "}" after dictionary elements.)"); + complete_extents(dictionary); return dictionary; } @@ -2685,6 +2801,8 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_grouping(ExpressionNode *p GDScriptParser::ExpressionNode *GDScriptParser::parse_attribute(ExpressionNode *p_previous_operand, bool p_can_assign) { SubscriptNode *attribute = alloc_node<SubscriptNode>(); + reset_extents(attribute, p_previous_operand); + update_extents(attribute); if (for_completion) { bool is_builtin = false; @@ -2704,17 +2822,21 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_attribute(ExpressionNode * attribute->base = p_previous_operand; if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected identifier after "." for attribute access.)")) { + complete_extents(attribute); return attribute; } attribute->is_attribute = true; attribute->attribute = parse_identifier(); + complete_extents(attribute); return attribute; } GDScriptParser::ExpressionNode *GDScriptParser::parse_subscript(ExpressionNode *p_previous_operand, bool p_can_assign) { SubscriptNode *subscript = alloc_node<SubscriptNode>(); + reset_extents(subscript, p_previous_operand); + update_extents(subscript); make_completion_context(COMPLETION_SUBSCRIPT, subscript); @@ -2727,15 +2849,19 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_subscript(ExpressionNode * pop_multiline(); consume(GDScriptTokenizer::Token::BRACKET_CLOSE, R"(Expected "]" after subscription index.)"); + complete_extents(subscript); return subscript; } GDScriptParser::ExpressionNode *GDScriptParser::parse_cast(ExpressionNode *p_previous_operand, bool p_can_assign) { CastNode *cast = alloc_node<CastNode>(); + reset_extents(cast, p_previous_operand); + update_extents(cast); cast->operand = p_previous_operand; cast->cast_type = parse_type(); + complete_extents(cast); if (cast->cast_type == nullptr) { push_error(R"(Expected type specifier after "as".)"); @@ -2747,6 +2873,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_cast(ExpressionNode *p_pre GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_previous_operand, bool p_can_assign) { CallNode *call = alloc_node<CallNode>(); + reset_extents(call, p_previous_operand); if (previous.type == GDScriptTokenizer::Token::SUPER) { // Super call. @@ -2757,6 +2884,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_pre if (current_function == nullptr) { push_error(R"(Cannot use implicit "super" call outside of a function.)"); pop_multiline(); + complete_extents(call); return nullptr; } if (current_function->identifier) { @@ -2769,6 +2897,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_pre make_completion_context(COMPLETION_SUPER_METHOD, call, true); if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected function name after ".".)")) { pop_multiline(); + complete_extents(call); return nullptr; } IdentifierNode *identifier = parse_identifier(); @@ -2825,6 +2954,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_call(ExpressionNode *p_pre pop_multiline(); consume(GDScriptTokenizer::Token::PARENTHESIS_CLOSE, R"*(Expected closing ")" after call arguments.)*"); + complete_extents(call); return call; } @@ -2868,6 +2998,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_get_node(ExpressionNode *p if (previous.type == GDScriptTokenizer::Token::PERCENT) { if (path_state != PATH_STATE_START && path_state != PATH_STATE_SLASH) { push_error(R"("%" is only valid in the beginning of a node name (either after "$" or after "/"))"); + complete_extents(get_node); return nullptr; } get_node->full_path += "%"; @@ -2876,6 +3007,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_get_node(ExpressionNode *p } else if (previous.type == GDScriptTokenizer::Token::SLASH) { if (path_state != PATH_STATE_START && path_state != PATH_STATE_NODE_NAME) { push_error(R"("/" is only valid at the beginning of the path or after a node name.)"); + complete_extents(get_node); return nullptr; } @@ -2903,6 +3035,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_get_node(ExpressionNode *p break; } push_error(vformat(R"(Expected node path as string or identifier after "%s".)", previous_token)); + complete_extents(get_node); return nullptr; } @@ -2916,10 +3049,12 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_get_node(ExpressionNode *p path_state = PATH_STATE_NODE_NAME; } else if (!check(GDScriptTokenizer::Token::SLASH) && !check(GDScriptTokenizer::Token::PERCENT)) { push_error(vformat(R"(Unexpected "%s" in node path.)", current.get_name())); + complete_extents(get_node); return nullptr; } } while (match(GDScriptTokenizer::Token::SLASH) || match(GDScriptTokenizer::Token::PERCENT)); + complete_extents(get_node); return get_node; } @@ -2943,6 +3078,7 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_preload(ExpressionNode *p_ pop_multiline(); consume(GDScriptTokenizer::Token::PARENTHESIS_CLOSE, R"*(Expected ")" after preload path.)*"); + complete_extents(preload); return preload; } @@ -2992,6 +3128,8 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_lambda(ExpressionNode *p_p in_lambda = true; function->body = parse_suite("lambda declaration", body, true); + complete_extents(function); + complete_extents(lambda); pop_multiline(); @@ -3036,13 +3174,15 @@ GDScriptParser::TypeNode *GDScriptParser::parse_type(bool p_allow_void) { if (!match(GDScriptTokenizer::Token::IDENTIFIER)) { if (match(GDScriptTokenizer::Token::VOID)) { if (p_allow_void) { - TypeNode *void_type = alloc_node<TypeNode>(); + complete_extents(type); + TypeNode *void_type = type; return void_type; } else { push_error(R"("void" is only allowed for a function return type.)"); } } // Leave error message to the caller who knows the context. + complete_extents(type); return nullptr; } @@ -3055,11 +3195,15 @@ GDScriptParser::TypeNode *GDScriptParser::parse_type(bool p_allow_void) { type->container_type = parse_type(false); // Don't allow void for array element type. if (type->container_type == nullptr) { push_error(R"(Expected type for collection after "[".)"); + complete_extents(type); type = nullptr; } else if (type->container_type->container_type != nullptr) { push_error("Nested typed collections are not supported."); } consume(GDScriptTokenizer::Token::BRACKET_CLOSE, R"(Expected closing "]" after collection type.)"); + if (type != nullptr) { + complete_extents(type); + } return type; } @@ -3072,6 +3216,7 @@ GDScriptParser::TypeNode *GDScriptParser::parse_type(bool p_allow_void) { } } + complete_extents(type); return type; } @@ -3280,7 +3425,16 @@ void GDScriptParser::get_class_doc_comment(int p_line, String &p_brief, String & p_tutorials.append(Pair<String, String>(title, link)); break; case DONE: - return; + break; + } + } + if (current_class->members.size() > 0) { + const ClassNode::Member &m = current_class->members[0]; + int first_member_line = m.get_line(); + if (first_member_line == line) { + p_brief = ""; + p_desc = ""; + p_tutorials.clear(); } } } @@ -3662,6 +3816,36 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node return true; } +template <PropertyUsageFlags t_usage> +bool GDScriptParser::export_group_annotations(const AnnotationNode *p_annotation, Node *p_node) { + AnnotationNode *annotation = const_cast<AnnotationNode *>(p_annotation); + + annotation->export_info.name = annotation->resolved_arguments[0]; + + switch (t_usage) { + case PROPERTY_USAGE_CATEGORY: { + annotation->export_info.usage = t_usage; + } break; + + case PROPERTY_USAGE_GROUP: { + annotation->export_info.usage = t_usage; + if (annotation->resolved_arguments.size() == 2) { + annotation->export_info.hint_string = annotation->resolved_arguments[1]; + } + } break; + + case PROPERTY_USAGE_SUBGROUP: { + annotation->export_info.usage = t_usage; + if (annotation->resolved_arguments.size() == 2) { + annotation->export_info.hint_string = annotation->resolved_arguments[1]; + } + } break; + } + + current_class->add_member_group(annotation); + return true; +} + bool GDScriptParser::warning_annotations(const AnnotationNode *p_annotation, Node *p_node) { #ifdef DEBUG_ENABLED bool has_error = false; @@ -3859,6 +4043,46 @@ GDScriptParser::DataType GDScriptParser::DataType::get_typed_container_type() co return type; } +void GDScriptParser::complete_extents(Node *p_node) { + while (!nodes_in_progress.is_empty() && nodes_in_progress.back()->get() != p_node) { + ERR_PRINT("Parser bug: Mismatch in extents tracking stack."); + nodes_in_progress.pop_back(); + } + if (nodes_in_progress.is_empty()) { + ERR_PRINT("Parser bug: Extents tracking stack is empty."); + } else { + nodes_in_progress.pop_back(); + } +} + +void GDScriptParser::update_extents(Node *p_node) { + p_node->end_line = previous.end_line; + p_node->end_column = previous.end_column; + p_node->leftmost_column = MIN(p_node->leftmost_column, previous.leftmost_column); + p_node->rightmost_column = MAX(p_node->rightmost_column, previous.rightmost_column); +} + +void GDScriptParser::reset_extents(Node *p_node, GDScriptTokenizer::Token p_token) { + p_node->start_line = p_token.start_line; + p_node->end_line = p_token.end_line; + p_node->start_column = p_token.start_column; + p_node->end_column = p_token.end_column; + p_node->leftmost_column = p_token.leftmost_column; + p_node->rightmost_column = p_token.rightmost_column; +} + +void GDScriptParser::reset_extents(Node *p_node, Node *p_from) { + if (p_from == nullptr) { + return; + } + p_node->start_line = p_from->start_line; + p_node->end_line = p_from->end_line; + p_node->start_column = p_from->start_column; + p_node->end_column = p_from->end_column; + p_node->leftmost_column = p_from->leftmost_column; + p_node->rightmost_column = p_from->rightmost_column; +} + /*---------- PRETTY PRINT FOR DEBUG ----------*/ #ifdef DEBUG_ENABLED @@ -4145,6 +4369,8 @@ void GDScriptParser::TreePrinter::print_class(ClassNode *p_class) { break; case ClassNode::Member::ENUM_VALUE: break; // Nothing. Will be printed by enum. + case ClassNode::Member::GROUP: + break; // Nothing. Groups are only used by inspector. case ClassNode::Member::UNDEFINED: push_line("<unknown member>"); break; diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index e3f8d4b8ba..9c97f98fbc 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -325,6 +325,7 @@ public: Vector<Variant> resolved_arguments; AnnotationInfo *info = nullptr; + PropertyInfo export_info; bool apply(GDScriptParser *p_this, Node *p_target) const; bool applies_to(uint32_t p_target_kinds) const; @@ -500,6 +501,7 @@ public: VARIABLE, ENUM, ENUM_VALUE, // For unnamed enums. + GROUP, // For member grouping. }; Type type = UNDEFINED; @@ -511,6 +513,7 @@ public: SignalNode *signal; VariableNode *variable; EnumNode *m_enum; + AnnotationNode *annotation; }; EnumNode::Value enum_value; @@ -532,6 +535,8 @@ public: return "enum"; case ENUM_VALUE: return "enum value"; + case GROUP: + return "group"; } return ""; } @@ -552,6 +557,8 @@ public: return m_enum->start_line; case SIGNAL: return signal->start_line; + case GROUP: + return annotation->start_line; case UNDEFINED: ERR_FAIL_V_MSG(-1, "Reaching undefined member type."); } @@ -586,6 +593,9 @@ public: // TODO: Add parameter info. return type; } + case GROUP: { + return DataType(); + } case UNDEFINED: return DataType(); } @@ -622,6 +632,10 @@ public: type = ENUM_VALUE; enum_value = p_enum_value; } + Member(AnnotationNode *p_annotation) { + type = GROUP; + annotation = p_annotation; + } }; IdentifierNode *identifier = nullptr; @@ -668,6 +682,10 @@ public: members_indices[p_enum_value.identifier->name] = members.size(); members.push_back(Member(p_enum_value)); } + void add_member_group(AnnotationNode *p_annotation_node) { + members_indices[p_annotation_node->export_info.name] = members.size(); + members.push_back(Member(p_annotation_node)); + } ClassNode() { type = CLASS; @@ -1238,6 +1256,7 @@ private: SIGNAL = 1 << 4, FUNCTION = 1 << 5, STATEMENT = 1 << 6, + STANDALONE = 1 << 7, CLASS_LEVEL = CLASS | VARIABLE | FUNCTION, }; uint32_t target_kind = 0; // Flags. @@ -1282,6 +1301,12 @@ private: }; static ParseRule *get_rule(GDScriptTokenizer::Token::Type p_token_type); + List<Node *> nodes_in_progress; + void complete_extents(Node *p_node); + void update_extents(Node *p_node); + void reset_extents(Node *p_node, GDScriptTokenizer::Token p_token); + void reset_extents(Node *p_node, Node *p_from); + template <class T> T *alloc_node() { T *node = memnew(T); @@ -1289,13 +1314,8 @@ private: node->next = list; list = node; - // TODO: Properly set positions for all nodes. - node->start_line = previous.start_line; - node->end_line = previous.end_line; - node->start_column = previous.start_column; - node->end_column = previous.end_column; - node->leftmost_column = previous.leftmost_column; - node->rightmost_column = previous.rightmost_column; + reset_extents(node, previous); + nodes_in_progress.push_back(node); return node; } @@ -1340,7 +1360,7 @@ private: SuiteNode *parse_suite(const String &p_context, SuiteNode *p_suite = nullptr, bool p_for_lambda = false); // Annotations AnnotationNode *parse_annotation(uint32_t p_valid_targets); - bool register_annotation(const MethodInfo &p_info, uint32_t p_target_kinds, AnnotationAction p_apply, int p_optional_arguments = 0, bool p_is_vararg = false); + bool register_annotation(const MethodInfo &p_info, uint32_t p_target_kinds, AnnotationAction p_apply, const Vector<Variant> &p_default_arguments = Vector<Variant>(), bool p_is_vararg = false); bool validate_annotation_arguments(AnnotationNode *p_annotation); void clear_unused_annotations(); bool tool_annotation(const AnnotationNode *p_annotation, Node *p_target); @@ -1348,6 +1368,8 @@ private: bool onready_annotation(const AnnotationNode *p_annotation, Node *p_target); template <PropertyHint t_hint, Variant::Type t_type> bool export_annotations(const AnnotationNode *p_annotation, Node *p_target); + template <PropertyUsageFlags t_usage> + bool export_group_annotations(const AnnotationNode *p_annotation, Node *p_target); bool warning_annotations(const AnnotationNode *p_annotation, Node *p_target); template <Multiplayer::RPCMode t_mode> bool network_annotations(const AnnotationNode *p_annotation, Node *p_target); @@ -1413,6 +1435,7 @@ public: CompletionContext get_completion_context() const { return completion_context; } CompletionCall get_completion_call() const { return completion_call; } void get_annotation_list(List<MethodInfo> *r_annotations) const; + bool annotation_exists(const String &p_annotation_name) const; const List<ParserError> &get_errors() const { return errors; } const List<String> get_dependencies() const { diff --git a/modules/gdscript/gdscript_rpc_callable.h b/modules/gdscript/gdscript_rpc_callable.h index 2c8734a74b..c8a91d6259 100644 --- a/modules/gdscript/gdscript_rpc_callable.h +++ b/modules/gdscript/gdscript_rpc_callable.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GDSCRIPT_RPC_CALLABLE -#define GDSCRIPT_RPC_CALLABLE +#ifndef GDSCRIPT_RPC_CALLABLE_H +#define GDSCRIPT_RPC_CALLABLE_H #include "core/variant/callable.h" #include "core/variant/variant.h" @@ -58,4 +58,4 @@ public: virtual ~GDScriptRPCCallable() = default; }; -#endif // GDSCRIPT_RPC_CALLABLE +#endif // GDSCRIPT_RPC_CALLABLE_H diff --git a/modules/gdscript/gdscript_tokenizer.h b/modules/gdscript/gdscript_tokenizer.h index 7fb715f2c8..68b2c6eb1c 100644 --- a/modules/gdscript/gdscript_tokenizer.h +++ b/modules/gdscript/gdscript_tokenizer.h @@ -273,4 +273,4 @@ public: GDScriptTokenizer(); }; -#endif +#endif // GDSCRIPT_TOKENIZER_H diff --git a/modules/gdscript/gdscript_utility_functions.cpp b/modules/gdscript/gdscript_utility_functions.cpp index a914374985..4b97486cb3 100644 --- a/modules/gdscript/gdscript_utility_functions.cpp +++ b/modules/gdscript/gdscript_utility_functions.cpp @@ -115,6 +115,7 @@ struct GDScriptUtilityFunctionsDefinitions { if (p_arg_count < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.argument = 1; + r_error.expected = 1; *r_ret = Variant(); return; } diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp index 1d56dae982..36ccb3d696 100644 --- a/modules/gdscript/gdscript_vm.cpp +++ b/modules/gdscript/gdscript_vm.cpp @@ -199,11 +199,14 @@ void (*type_init_function_table[])(Variant *) = { &VariantInitializer<Vector3>::init, // VECTOR3. &VariantInitializer<Vector3i>::init, // VECTOR3I. &VariantInitializer<Transform2D>::init, // TRANSFORM2D. + &VariantInitializer<Vector4>::init, // VECTOR4. + &VariantInitializer<Vector4i>::init, // VECTOR4I. &VariantInitializer<Plane>::init, // PLANE. &VariantInitializer<Quaternion>::init, // QUATERNION. &VariantInitializer<AABB>::init, // AABB. &VariantInitializer<Basis>::init, // BASIS. &VariantInitializer<Transform3D>::init, // TRANSFORM3D. + &VariantInitializer<Projection>::init, // PROJECTION. &VariantInitializer<Color>::init, // COLOR. &VariantInitializer<StringName>::init, // STRING_NAME. &VariantInitializer<NodePath>::init, // NODE_PATH. @@ -282,11 +285,14 @@ void (*type_init_function_table[])(Variant *) = { &&OPCODE_CALL_PTRCALL_VECTOR3, \ &&OPCODE_CALL_PTRCALL_VECTOR3I, \ &&OPCODE_CALL_PTRCALL_TRANSFORM2D, \ + &&OPCODE_CALL_PTRCALL_VECTOR4, \ + &&OPCODE_CALL_PTRCALL_VECTOR4I, \ &&OPCODE_CALL_PTRCALL_PLANE, \ &&OPCODE_CALL_PTRCALL_QUATERNION, \ &&OPCODE_CALL_PTRCALL_AABB, \ &&OPCODE_CALL_PTRCALL_BASIS, \ &&OPCODE_CALL_PTRCALL_TRANSFORM3D, \ + &&OPCODE_CALL_PTRCALL_PROJECTION, \ &&OPCODE_CALL_PTRCALL_COLOR, \ &&OPCODE_CALL_PTRCALL_STRING_NAME, \ &&OPCODE_CALL_PTRCALL_NODE_PATH, \ @@ -372,11 +378,14 @@ void (*type_init_function_table[])(Variant *) = { &&OPCODE_TYPE_ADJUST_VECTOR3, \ &&OPCODE_TYPE_ADJUST_VECTOR3I, \ &&OPCODE_TYPE_ADJUST_TRANSFORM2D, \ + &&OPCODE_TYPE_ADJUST_VECTOR4, \ + &&OPCODE_TYPE_ADJUST_VECTOR4I, \ &&OPCODE_TYPE_ADJUST_PLANE, \ &&OPCODE_TYPE_ADJUST_QUATERNION, \ &&OPCODE_TYPE_ADJUST_AABB, \ &&OPCODE_TYPE_ADJUST_BASIS, \ &&OPCODE_TYPE_ADJUST_TRANSFORM3D, \ + &&OPCODE_TYPE_ADJUST_PROJECTION, \ &&OPCODE_TYPE_ADJUST_COLOR, \ &&OPCODE_TYPE_ADJUST_STRING_NAME, \ &&OPCODE_TYPE_ADJUST_NODE_PATH, \ @@ -435,6 +444,8 @@ void (*type_init_function_table[])(Variant *) = { #define OP_GET_VECTOR3 get_vector3 #define OP_GET_VECTOR3I get_vector3i #define OP_GET_RECT2 get_rect2 +#define OP_GET_VECTOR4 get_vector4 +#define OP_GET_VECTOR4I get_vector4i #define OP_GET_RECT2I get_rect2i #define OP_GET_QUATERNION get_quaternion #define OP_GET_COLOR get_color @@ -456,6 +467,7 @@ void (*type_init_function_table[])(Variant *) = { #define OP_GET_PACKED_COLOR_ARRAY get_color_array #define OP_GET_TRANSFORM3D get_transform #define OP_GET_TRANSFORM2D get_transform2d +#define OP_GET_PROJECTION get_projection #define OP_GET_PLANE get_plane #define OP_GET_AABB get_aabb #define OP_GET_BASIS get_basis @@ -1032,11 +1044,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a #endif #ifdef DEBUG_ENABLED if (!valid) { - if (src->has_method(*index)) { - err_text = "Invalid get index '" + index->operator String() + "' (on base: '" + _get_var_type(src) + "'). Did you mean '." + index->operator String() + "()' or funcref(obj, \"" + index->operator String() + "\") ?"; - } else { - err_text = "Invalid get index '" + index->operator String() + "' (on base: '" + _get_var_type(src) + "')."; - } + err_text = "Invalid get index '" + index->operator String() + "' (on base: '" + _get_var_type(src) + "')."; OPCODE_BREAK; } *dst = ret; @@ -1831,11 +1839,14 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE_CALL_PTR(VECTOR3); OPCODE_CALL_PTR(VECTOR3I); OPCODE_CALL_PTR(TRANSFORM2D); + OPCODE_CALL_PTR(VECTOR4); + OPCODE_CALL_PTR(VECTOR4I); OPCODE_CALL_PTR(PLANE); OPCODE_CALL_PTR(QUATERNION); OPCODE_CALL_PTR(AABB); OPCODE_CALL_PTR(BASIS); OPCODE_CALL_PTR(TRANSFORM3D); + OPCODE_CALL_PTR(PROJECTION); OPCODE_CALL_PTR(COLOR); OPCODE_CALL_PTR(STRING_NAME); OPCODE_CALL_PTR(NODE_PATH); @@ -3284,6 +3295,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a int globalname_idx = _code_ptr[ip + 2]; GD_ERR_BREAK(globalname_idx < 0 || globalname_idx >= _global_names_count); const StringName *globalname = &_global_names_ptr[globalname_idx]; + GD_ERR_BREAK(!GDScriptLanguage::get_singleton()->get_named_globals_map().has(*globalname)); GET_INSTRUCTION_ARG(dst, 0); *dst = GDScriptLanguage::get_singleton()->get_named_globals_map()[*globalname]; @@ -3312,11 +3324,14 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a OPCODE_TYPE_ADJUST(VECTOR3, Vector3); OPCODE_TYPE_ADJUST(VECTOR3I, Vector3i); OPCODE_TYPE_ADJUST(TRANSFORM2D, Transform2D); + OPCODE_TYPE_ADJUST(VECTOR4, Vector4); + OPCODE_TYPE_ADJUST(VECTOR4I, Vector4i); OPCODE_TYPE_ADJUST(PLANE, Plane); OPCODE_TYPE_ADJUST(QUATERNION, Quaternion); OPCODE_TYPE_ADJUST(AABB, AABB); OPCODE_TYPE_ADJUST(BASIS, Basis); OPCODE_TYPE_ADJUST(TRANSFORM3D, Transform3D); + OPCODE_TYPE_ADJUST(PROJECTION, Projection); OPCODE_TYPE_ADJUST(COLOR, Color); OPCODE_TYPE_ADJUST(STRING_NAME, StringName); OPCODE_TYPE_ADJUST(NODE_PATH, NodePath); diff --git a/modules/gdscript/gdscript_warning.h b/modules/gdscript/gdscript_warning.h index f47f31aedf..a639e7b44e 100644 --- a/modules/gdscript/gdscript_warning.h +++ b/modules/gdscript/gdscript_warning.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GDSCRIPT_WARNINGS -#define GDSCRIPT_WARNINGS +#ifndef GDSCRIPT_WARNING_H +#define GDSCRIPT_WARNING_H #ifdef DEBUG_ENABLED @@ -97,4 +97,4 @@ public: #endif // DEBUG_ENABLED -#endif // GDSCRIPT_WARNINGS +#endif // GDSCRIPT_WARNING_H diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp index d3c5fed95a..03e93821c7 100644 --- a/modules/gdscript/language_server/gdscript_extend_parser.cpp +++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp @@ -307,6 +307,8 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p parse_class_symbol(m.m_class, symbol); r_symbol.children.push_back(symbol); } break; + case ClassNode::Member::GROUP: + break; // No-op, but silences warnings. case ClassNode::Member::UNDEFINED: break; // Unreachable. } @@ -815,6 +817,8 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode methods.append(dump_function_api(m.function)); } } break; + case ClassNode::Member::GROUP: + break; // No-op, but silences warnings. case ClassNode::Member::UNDEFINED: break; // Unreachable. } diff --git a/modules/gdscript/language_server/gdscript_extend_parser.h b/modules/gdscript/language_server/gdscript_extend_parser.h index 99b0bf45d0..08bba4a2d4 100644 --- a/modules/gdscript/language_server/gdscript_extend_parser.h +++ b/modules/gdscript/language_server/gdscript_extend_parser.h @@ -33,7 +33,7 @@ #include "../gdscript_parser.h" #include "core/variant/variant.h" -#include "lsp.hpp" +#include "godot_lsp.h" #ifndef LINE_NUMBER_TO_INDEX #define LINE_NUMBER_TO_INDEX(p_line) ((p_line)-1) @@ -99,4 +99,4 @@ public: Error parse(const String &p_code, const String &p_path); }; -#endif +#endif // GDSCRIPT_EXTEND_PARSER_H diff --git a/modules/gdscript/language_server/gdscript_language_protocol.h b/modules/gdscript/language_server/gdscript_language_protocol.h index 0fed8597f9..3c9cfe512f 100644 --- a/modules/gdscript/language_server/gdscript_language_protocol.h +++ b/modules/gdscript/language_server/gdscript_language_protocol.h @@ -36,7 +36,7 @@ #include "core/io/tcp_server.h" #include "gdscript_text_document.h" #include "gdscript_workspace.h" -#include "lsp.hpp" +#include "godot_lsp.h" #include "modules/modules_enabled.gen.h" // For jsonrpc. #ifdef MODULE_JSONRPC_ENABLED diff --git a/modules/gdscript/language_server/gdscript_text_document.h b/modules/gdscript/language_server/gdscript_text_document.h index 9732765f34..87bc08a34e 100644 --- a/modules/gdscript/language_server/gdscript_text_document.h +++ b/modules/gdscript/language_server/gdscript_text_document.h @@ -33,7 +33,7 @@ #include "core/io/file_access.h" #include "core/object/ref_counted.h" -#include "lsp.hpp" +#include "godot_lsp.h" class GDScriptTextDocument : public RefCounted { GDCLASS(GDScriptTextDocument, RefCounted) @@ -77,4 +77,4 @@ public: GDScriptTextDocument(); }; -#endif +#endif // GDSCRIPT_TEXT_DOCUMENT_H diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp index 8d484a43b3..959651c024 100644 --- a/modules/gdscript/language_server/gdscript_workspace.cpp +++ b/modules/gdscript/language_server/gdscript_workspace.cpp @@ -499,7 +499,9 @@ Error GDScriptWorkspace::parse_local_script(const String &p_path) { String GDScriptWorkspace::get_file_path(const String &p_uri) const { String path = p_uri; - path = path.replace(root_uri + "/", "res://"); + path = path.replace("///", "//"); + path = path.replace("%3A", ":"); + path = path.replacen(root_uri + "/", "res://"); path = path.uri_decode(); return path; } diff --git a/modules/gdscript/language_server/gdscript_workspace.h b/modules/gdscript/language_server/gdscript_workspace.h index 7bff5db81f..88f3aaf957 100644 --- a/modules/gdscript/language_server/gdscript_workspace.h +++ b/modules/gdscript/language_server/gdscript_workspace.h @@ -35,7 +35,7 @@ #include "core/variant/variant.h" #include "editor/editor_file_system.h" #include "gdscript_extend_parser.h" -#include "lsp.hpp" +#include "godot_lsp.h" class GDScriptWorkspace : public RefCounted { GDCLASS(GDScriptWorkspace, RefCounted); @@ -100,4 +100,4 @@ public: ~GDScriptWorkspace(); }; -#endif +#endif // GDSCRIPT_WORKSPACE_H diff --git a/modules/gdscript/language_server/lsp.hpp b/modules/gdscript/language_server/godot_lsp.h index 1c9349097f..fbd40796c4 100644 --- a/modules/gdscript/language_server/lsp.hpp +++ b/modules/gdscript/language_server/godot_lsp.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* lsp.hpp */ +/* godot_lsp.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -1975,4 +1975,4 @@ static String marked_documentation(const String &p_bbcode) { } } // namespace lsp -#endif +#endif // GODOT_LSP_H diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index b230c6ba36..059ca703ab 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -52,10 +52,10 @@ GDScriptCache *gdscript_cache = nullptr; #ifdef TOOLS_ENABLED -#include "editor/editor_export.h" #include "editor/editor_node.h" #include "editor/editor_settings.h" #include "editor/editor_translation_parser.h" +#include "editor/export/editor_export.h" #include "editor/gdscript_highlighter.h" #include "editor/gdscript_translation_parser_plugin.h" diff --git a/modules/gdscript/tests/gdscript_test_runner.h b/modules/gdscript/tests/gdscript_test_runner.h index ee21afd9c9..033d2fcad1 100644 --- a/modules/gdscript/tests/gdscript_test_runner.h +++ b/modules/gdscript/tests/gdscript_test_runner.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GDSCRIPT_TEST_H -#define GDSCRIPT_TEST_H +#ifndef GDSCRIPT_TEST_RUNNER_H +#define GDSCRIPT_TEST_RUNNER_H #include "../gdscript.h" #include "core/error/error_macros.h" @@ -123,4 +123,4 @@ public: } // namespace GDScriptTests -#endif // GDSCRIPT_TEST_H +#endif // GDSCRIPT_TEST_RUNNER_H diff --git a/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd b/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd index d13d713454..ada6030132 100644 --- a/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd +++ b/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.gd @@ -1,6 +1,6 @@ -# Error here. `class_name` should be used *before* annotations, not after. +# Error here. `class_name` should be used *before* annotations, not after (except @tool). @icon("res://path/to/optional/icon.svg") class_name HelloWorld func test(): - pass + pass diff --git a/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.out b/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.out index 0bcc8acc55..02b33c8692 100644 --- a/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.out +++ b/modules/gdscript/tests/scripts/parser/errors/class_name_after_annotation.out @@ -1,2 +1,2 @@ GDTEST_PARSER_ERROR -"class_name" should be used before annotations. +"class_name" should be used before annotations (except @tool). diff --git a/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_for_variable.gd b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_for_variable.gd new file mode 100644 index 0000000000..409da11051 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_for_variable.gd @@ -0,0 +1,4 @@ +func test(): + var TEST = 1 + for TEST in 2: + pass diff --git a/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_for_variable.out b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_for_variable.out new file mode 100644 index 0000000000..407f094ca0 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_for_variable.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +There is already a variable named "TEST" declared in this scope. diff --git a/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_variable.gd b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_variable.gd new file mode 100644 index 0000000000..b353fd1288 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_variable.gd @@ -0,0 +1,3 @@ +func test(): + var TEST = 1 + var TEST = 2 diff --git a/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_variable.out b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_variable.out new file mode 100644 index 0000000000..407f094ca0 --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/variable_conflicts_variable.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +There is already a variable named "TEST" declared in this scope. diff --git a/modules/glslang/register_types.cpp b/modules/glslang/register_types.cpp index 64891d9ee8..b1c2140039 100644 --- a/modules/glslang/register_types.cpp +++ b/modules/glslang/register_types.cpp @@ -38,7 +38,8 @@ #include <glslang/Public/ShaderLang.h> #include <glslang/SPIRV/GlslangToSpv.h> -static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage, const String &p_source_code, RenderingDevice::ShaderLanguage p_language, String *r_error, const RenderingDevice::Capabilities *p_capabilities) { +static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage, const String &p_source_code, RenderingDevice::ShaderLanguage p_language, String *r_error, const RenderingDevice *p_render_device) { + const RD::Capabilities *capabilities = p_render_device->get_device_capabilities(); Vector<uint8_t> ret; ERR_FAIL_COND_V(p_language == RenderingDevice::SHADER_LANGUAGE_HLSL, ret); @@ -58,12 +59,12 @@ static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage glslang::EShTargetLanguageVersion TargetVersion = glslang::EShTargetSpv_1_5; glslang::TShader::ForbidIncluder includer; - if (p_capabilities->device_family == RenderingDevice::DeviceFamily::DEVICE_VULKAN) { - if (p_capabilities->version_major == 1 && p_capabilities->version_minor == 0) { + if (capabilities->device_family == RenderingDevice::DeviceFamily::DEVICE_VULKAN) { + if (capabilities->version_major == 1 && capabilities->version_minor == 0) { ClientVersion = glslang::EShTargetVulkan_1_0; TargetVersion = glslang::EShTargetSpv_1_0; check_subgroup_support = false; // subgroups are not supported in Vulkan 1.0 - } else if (p_capabilities->version_major == 1 && p_capabilities->version_minor == 1) { + } else if (capabilities->version_major == 1 && capabilities->version_minor == 1) { ClientVersion = glslang::EShTargetVulkan_1_1; TargetVersion = glslang::EShTargetSpv_1_3; } else { @@ -90,34 +91,36 @@ static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage if (check_subgroup_support) { uint32_t stage_bit = 1 << p_stage; - if ((p_capabilities->subgroup_in_shaders & stage_bit) == stage_bit) { + uint32_t subgroup_in_shaders = uint32_t(p_render_device->limit_get(RD::LIMIT_SUBGROUP_IN_SHADERS)); + uint32_t subgroup_operations = uint32_t(p_render_device->limit_get(RD::LIMIT_SUBGROUP_OPERATIONS)); + if ((subgroup_in_shaders & stage_bit) == stage_bit) { // stage supports subgroups preamble += "#define has_GL_KHR_shader_subgroup_basic 1\n"; - if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_VOTE_BIT) { + if (subgroup_operations & RenderingDevice::SUBGROUP_VOTE_BIT) { preamble += "#define has_GL_KHR_shader_subgroup_vote 1\n"; } - if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_ARITHMETIC_BIT) { + if (subgroup_operations & RenderingDevice::SUBGROUP_ARITHMETIC_BIT) { preamble += "#define has_GL_KHR_shader_subgroup_arithmetic 1\n"; } - if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_BALLOT_BIT) { + if (subgroup_operations & RenderingDevice::SUBGROUP_BALLOT_BIT) { preamble += "#define has_GL_KHR_shader_subgroup_ballot 1\n"; } - if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_SHUFFLE_BIT) { + if (subgroup_operations & RenderingDevice::SUBGROUP_SHUFFLE_BIT) { preamble += "#define has_GL_KHR_shader_subgroup_shuffle 1\n"; } - if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_SHUFFLE_RELATIVE_BIT) { + if (subgroup_operations & RenderingDevice::SUBGROUP_SHUFFLE_RELATIVE_BIT) { preamble += "#define has_GL_KHR_shader_subgroup_shuffle_relative 1\n"; } - if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_CLUSTERED_BIT) { + if (subgroup_operations & RenderingDevice::SUBGROUP_CLUSTERED_BIT) { preamble += "#define has_GL_KHR_shader_subgroup_clustered 1\n"; } - if (p_capabilities->subgroup_operations & RenderingDevice::SUBGROUP_QUAD_BIT) { + if (subgroup_operations & RenderingDevice::SUBGROUP_QUAD_BIT) { preamble += "#define has_GL_KHR_shader_subgroup_quad 1\n"; } } } - if (p_capabilities->supports_multiview) { + if (p_render_device->has_feature(RD::SUPPORTS_MULTIVIEW)) { preamble += "#define has_VK_KHR_multiview 1\n"; } @@ -184,9 +187,10 @@ static Vector<uint8_t> _compile_shader_glsl(RenderingDevice::ShaderStage p_stage return ret; } -static String _get_cache_key_function_glsl(const RenderingDevice::Capabilities *p_capabilities) { +static String _get_cache_key_function_glsl(const RenderingDevice *p_render_device) { + const RD::Capabilities *capabilities = p_render_device->get_device_capabilities(); String version; - version = "SpirVGen=" + itos(glslang::GetSpirvGeneratorVersion()) + ", major=" + itos(p_capabilities->version_major) + ", minor=" + itos(p_capabilities->version_minor) + " , subgroup_size=" + itos(p_capabilities->subgroup_operations) + " , subgroup_ops=" + itos(p_capabilities->subgroup_operations) + " , subgroup_in_shaders=" + itos(p_capabilities->subgroup_in_shaders); + version = "SpirVGen=" + itos(glslang::GetSpirvGeneratorVersion()) + ", major=" + itos(capabilities->version_major) + ", minor=" + itos(capabilities->version_minor) + " , subgroup_size=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_SIZE)) + " , subgroup_ops=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_OPERATIONS)) + " , subgroup_in_shaders=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_IN_SHADERS)); return version; } diff --git a/modules/gltf/README.md b/modules/gltf/README.md new file mode 100644 index 0000000000..5d8966b201 --- /dev/null +++ b/modules/gltf/README.md @@ -0,0 +1,11 @@ +# Godot GLTF import and export module + +In a nutshell, the GLTF module works like this: + +* The [`structures/`](structures/) folder contains GLTF structures, the + small pieces that make up a GLTF file, represented as C++ classes. +* The [`extensions/`](extensions/) folder contains GLTF extensions, which + are optional features that build on top of the base GLTF spec. +* [`GLTFState`](gltf_state.h) holds collections of structures and extensions. +* [`GLTFDocument`](gltf_document.h) operates on GLTFState and its elements. +* The [`editor/`](editor/) folder uses GLTFDocument to import and export 3D models. diff --git a/modules/gltf/SCsub b/modules/gltf/SCsub index 3379404a00..6634d5df7b 100644 --- a/modules/gltf/SCsub +++ b/modules/gltf/SCsub @@ -7,5 +7,7 @@ env_gltf = env_modules.Clone() # Godot's own source files env_gltf.add_source_files(env.modules_sources, "*.cpp") +env_gltf.add_source_files(env.modules_sources, "extensions/*.cpp") +env_gltf.add_source_files(env.modules_sources, "structures/*.cpp") if env["tools"]: env_gltf.add_source_files(env.modules_sources, "editor/*.cpp") diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp index 676862ea5a..8002c185c7 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.cpp +++ b/modules/gltf/editor/editor_scene_importer_blend.cpp @@ -292,7 +292,7 @@ static bool _test_blender_path(const String &p_path, String *r_err = nullptr) { path = path.plus_file("blender"); #endif -#if defined(OSX_ENABLED) +#if defined(MACOS_ENABLED) if (!FileAccess::exists(path)) { path = path.plus_file("Blender"); } @@ -449,8 +449,8 @@ bool EditorFileSystemImportFormatSupportQueryBlend::query() { EditorNode::get_singleton()->get_gui_base()->add_child(configure_blender_dialog); - configure_blender_dialog->get_ok_button()->set_text(TTR("Confirm Path")); - configure_blender_dialog->get_cancel_button()->set_text(TTR("Disable '.blend' Import")); + configure_blender_dialog->set_ok_button_text(TTR("Confirm Path")); + configure_blender_dialog->set_cancel_button_text(TTR("Disable '.blend' Import")); configure_blender_dialog->get_cancel_button()->set_tooltip(TTR("Disables Blender '.blend' files import for this project. Can be re-enabled in Project Settings.")); configure_blender_dialog->connect("confirmed", callable_mp(this, &EditorFileSystemImportFormatSupportQueryBlend::_path_confirmed)); @@ -468,7 +468,7 @@ bool EditorFileSystemImportFormatSupportQueryBlend::query() { // Autodetect auto_detected_path = ""; -#if defined(OSX_ENABLED) +#if defined(MACOS_ENABLED) { Vector<String> mdfind_paths; diff --git a/modules/gltf/gltf_light.cpp b/modules/gltf/extensions/gltf_light.cpp index af21a4e804..af21a4e804 100644 --- a/modules/gltf/gltf_light.cpp +++ b/modules/gltf/extensions/gltf_light.cpp diff --git a/modules/gltf/gltf_light.h b/modules/gltf/extensions/gltf_light.h index 25e0835a33..58fa299dfd 100644 --- a/modules/gltf/gltf_light.h +++ b/modules/gltf/extensions/gltf_light.h @@ -33,6 +33,7 @@ #include "core/config/engine.h" #include "core/io/resource.h" +#include "scene/3d/light_3d.h" class GLTFLight : public Resource { GDCLASS(GLTFLight, Resource) diff --git a/modules/gltf/gltf_spec_gloss.cpp b/modules/gltf/extensions/gltf_spec_gloss.cpp index 83af91bfcc..83af91bfcc 100644 --- a/modules/gltf/gltf_spec_gloss.cpp +++ b/modules/gltf/extensions/gltf_spec_gloss.cpp diff --git a/modules/gltf/gltf_spec_gloss.h b/modules/gltf/extensions/gltf_spec_gloss.h index f8a431bdce..a45fa4296c 100644 --- a/modules/gltf/gltf_spec_gloss.h +++ b/modules/gltf/extensions/gltf_spec_gloss.h @@ -64,4 +64,5 @@ public: Ref<Image> get_spec_gloss_img(); void set_spec_gloss_img(Ref<Image> p_spec_gloss_img); }; + #endif // GLTF_SPEC_GLOSS_H diff --git a/modules/gltf/gltf_defines.h b/modules/gltf/gltf_defines.h new file mode 100644 index 0000000000..c20c87f798 --- /dev/null +++ b/modules/gltf/gltf_defines.h @@ -0,0 +1,87 @@ +/*************************************************************************/ +/* gltf_defines.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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. */ +/*************************************************************************/ + +#ifndef GLTF_DEFINES_H +#define GLTF_DEFINES_H + +// This file should only be included by other headers. + +// Godot classes used by GLTF headers. +class BoneAttachment3D; +class CSGShape3D; +class DirectionalLight3D; +class GridMap; +class Light3D; +class MultiMeshInstance3D; +class Skeleton3D; +class Skin; + +// GLTF classes. +struct GLTFAccessor; +class GLTFAnimation; +class GLTFBufferView; +class GLTFCamera; +class GLTFDocument; +class GLTFDocumentExtension; +class GLTFLight; +class GLTFMesh; +class GLTFNode; +class GLTFSkeleton; +class GLTFSkin; +class GLTFSpecGloss; +class GLTFState; +class GLTFTexture; + +// GLTF index aliases. +using GLTFAccessorIndex = int; +using GLTFAnimationIndex = int; +using GLTFBufferIndex = int; +using GLTFBufferViewIndex = int; +using GLTFCameraIndex = int; +using GLTFImageIndex = int; +using GLTFMaterialIndex = int; +using GLTFMeshIndex = int; +using GLTFLightIndex = int; +using GLTFNodeIndex = int; +using GLTFSkeletonIndex = int; +using GLTFSkinIndex = int; +using GLTFTextureIndex = int; + +enum GLTFType { + TYPE_SCALAR, + TYPE_VEC2, + TYPE_VEC3, + TYPE_VEC4, + TYPE_MAT2, + TYPE_MAT3, + TYPE_MAT4, +}; + +#endif // GLTF_DEFINES_H diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index 2017355717..4ca8482ba3 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -30,19 +30,10 @@ #include "gltf_document.h" -#include "gltf_accessor.h" -#include "gltf_animation.h" -#include "gltf_camera.h" +#include "extensions/gltf_spec_gloss.h" #include "gltf_document_extension.h" #include "gltf_document_extension_convert_importer_mesh.h" -#include "gltf_light.h" -#include "gltf_mesh.h" -#include "gltf_node.h" -#include "gltf_skeleton.h" -#include "gltf_skin.h" -#include "gltf_spec_gloss.h" #include "gltf_state.h" -#include "gltf_texture.h" #include "core/crypto/crypto_core.h" #include "core/error/error_macros.h" @@ -230,15 +221,21 @@ Error GLTFDocument::_serialize(Ref<GLTFState> state, const String &p_path) { } Error GLTFDocument::_serialize_extensions(Ref<GLTFState> state) const { - const String texture_transform = "KHR_texture_transform"; - const String punctual_lights = "KHR_lights_punctual"; Array extensions_used; - extensions_used.push_back(punctual_lights); - extensions_used.push_back(texture_transform); - state->json["extensionsUsed"] = extensions_used; Array extensions_required; - extensions_required.push_back(texture_transform); - state->json["extensionsRequired"] = extensions_required; + if (!state->lights.is_empty()) { + extensions_used.push_back("KHR_lights_punctual"); + } + if (state->use_khr_texture_transform) { + extensions_used.push_back("KHR_texture_transform"); + extensions_required.push_back("KHR_texture_transform"); + } + if (!extensions_used.is_empty()) { + state->json["extensionsUsed"] = extensions_used; + } + if (!extensions_required.is_empty()) { + state->json["extensionsRequired"] = extensions_required; + } return OK; } @@ -934,58 +931,58 @@ Error GLTFDocument::_encode_accessors(Ref<GLTFState> state) { return OK; } -String GLTFDocument::_get_accessor_type_name(const GLTFDocument::GLTFType p_type) { - if (p_type == GLTFDocument::TYPE_SCALAR) { +String GLTFDocument::_get_accessor_type_name(const GLTFType p_type) { + if (p_type == GLTFType::TYPE_SCALAR) { return "SCALAR"; } - if (p_type == GLTFDocument::TYPE_VEC2) { + if (p_type == GLTFType::TYPE_VEC2) { return "VEC2"; } - if (p_type == GLTFDocument::TYPE_VEC3) { + if (p_type == GLTFType::TYPE_VEC3) { return "VEC3"; } - if (p_type == GLTFDocument::TYPE_VEC4) { + if (p_type == GLTFType::TYPE_VEC4) { return "VEC4"; } - if (p_type == GLTFDocument::TYPE_MAT2) { + if (p_type == GLTFType::TYPE_MAT2) { return "MAT2"; } - if (p_type == GLTFDocument::TYPE_MAT3) { + if (p_type == GLTFType::TYPE_MAT3) { return "MAT3"; } - if (p_type == GLTFDocument::TYPE_MAT4) { + if (p_type == GLTFType::TYPE_MAT4) { return "MAT4"; } ERR_FAIL_V("SCALAR"); } -GLTFDocument::GLTFType GLTFDocument::_get_type_from_str(const String &p_string) { +GLTFType GLTFDocument::_get_type_from_str(const String &p_string) { if (p_string == "SCALAR") { - return GLTFDocument::TYPE_SCALAR; + return GLTFType::TYPE_SCALAR; } if (p_string == "VEC2") { - return GLTFDocument::TYPE_VEC2; + return GLTFType::TYPE_VEC2; } if (p_string == "VEC3") { - return GLTFDocument::TYPE_VEC3; + return GLTFType::TYPE_VEC3; } if (p_string == "VEC4") { - return GLTFDocument::TYPE_VEC4; + return GLTFType::TYPE_VEC4; } if (p_string == "MAT2") { - return GLTFDocument::TYPE_MAT2; + return GLTFType::TYPE_MAT2; } if (p_string == "MAT3") { - return GLTFDocument::TYPE_MAT3; + return GLTFType::TYPE_MAT3; } if (p_string == "MAT4") { - return GLTFDocument::TYPE_MAT4; + return GLTFType::TYPE_MAT4; } - ERR_FAIL_V(GLTFDocument::TYPE_SCALAR); + ERR_FAIL_V(GLTFType::TYPE_SCALAR); } Error GLTFDocument::_parse_accessors(Ref<GLTFState> state) { @@ -1536,7 +1533,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_ints(Ref<GLTFState> state, c accessor.instantiate(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFDocument::GLTFType type = GLTFDocument::TYPE_SCALAR; + const GLTFType type = GLTFType::TYPE_SCALAR; const int component_type = GLTFDocument::COMPONENT_TYPE_INT; accessor->max = type_max; @@ -1620,7 +1617,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec2(Ref<GLTFState> state, c accessor.instantiate(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC2; + const GLTFType type = GLTFType::TYPE_VEC2; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; accessor->max = type_max; @@ -1669,7 +1666,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_color(Ref<GLTFState> state, accessor.instantiate(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC4; + const GLTFType type = GLTFType::TYPE_VEC4; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; accessor->max = type_max; @@ -1734,7 +1731,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_weights(Ref<GLTFState> state accessor.instantiate(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC4; + const GLTFType type = GLTFType::TYPE_VEC4; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; accessor->max = type_max; @@ -1781,7 +1778,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_joints(Ref<GLTFState> state, accessor.instantiate(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC4; + const GLTFType type = GLTFType::TYPE_VEC4; const int component_type = GLTFDocument::COMPONENT_TYPE_UNSIGNED_SHORT; accessor->max = type_max; @@ -1830,7 +1827,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_quaternions(Ref<GLTFState> s accessor.instantiate(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC4; + const GLTFType type = GLTFType::TYPE_VEC4; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; accessor->max = type_max; @@ -1895,7 +1892,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_floats(Ref<GLTFState> state, accessor.instantiate(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFDocument::GLTFType type = GLTFDocument::TYPE_SCALAR; + const GLTFType type = GLTFType::TYPE_SCALAR; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; accessor->max = type_max; @@ -1941,7 +1938,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_vec3(Ref<GLTFState> state, c accessor.instantiate(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFDocument::GLTFType type = GLTFDocument::TYPE_VEC3; + const GLTFType type = GLTFType::TYPE_VEC3; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; accessor->max = type_max; @@ -2009,7 +2006,7 @@ GLTFAccessorIndex GLTFDocument::_encode_accessor_as_xform(Ref<GLTFState> state, accessor.instantiate(); GLTFBufferIndex buffer_view_i; int64_t size = state->buffers[0].size(); - const GLTFDocument::GLTFType type = GLTFDocument::TYPE_MAT4; + const GLTFType type = GLTFType::TYPE_MAT4; const int component_type = GLTFDocument::COMPONENT_TYPE_FLOAT; accessor->max = type_max; @@ -3080,9 +3077,9 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_pat // We'll assume that we use either URI or bufferView, so let's warn the user // if their image somehow uses both. And fail if it has neither. - ERR_CONTINUE_MSG(!d.has("uri") && !d.has("bufferView"), "Invalid image definition in glTF file, it should specific an 'uri' or 'bufferView'."); + ERR_CONTINUE_MSG(!d.has("uri") && !d.has("bufferView"), "Invalid image definition in glTF file, it should specify an 'uri' or 'bufferView'."); if (d.has("uri") && d.has("bufferView")) { - WARN_PRINT("Invalid image definition in glTF file using both 'uri' and 'bufferView'. 'bufferView' will take precedence."); + WARN_PRINT("Invalid image definition in glTF file using both 'uri' and 'bufferView'. 'uri' will take precedence."); } String mimetype; @@ -3202,12 +3199,7 @@ Error GLTFDocument::_parse_images(Ref<GLTFState> state, const String &p_base_pat state->images.push_back(Ref<Texture2D>()); continue; } - - Ref<ImageTexture> t; - t.instantiate(); - t->create_from_image(img); - - state->images.push_back(t); + state->images.push_back(ImageTexture::create_from_image(img)); } print_verbose("glTF: Total images: " + itos(state->images.size())); @@ -3310,7 +3302,11 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { } if (gltf_texture_index != -1) { bct["index"] = gltf_texture_index; - bct["extensions"] = _serialize_texture_transform_uv1(material); + Dictionary extensions = _serialize_texture_transform_uv1(material); + if (!extensions.is_empty()) { + bct["extensions"] = extensions; + state->use_khr_texture_transform = true; + } mr["baseColorTexture"] = bct; } } @@ -3428,7 +3424,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { } } orm_image->generate_mipmaps(); - orm_texture->create_from_image(orm_image); + orm_texture->set_image(orm_image); GLTFTextureIndex orm_texture_index = -1; if (has_ao || has_roughness || has_metalness) { orm_texture->set_name(material->get_name() + "_orm"); @@ -3441,7 +3437,11 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { } if (has_roughness || has_metalness) { mrt["index"] = orm_texture_index; - mrt["extensions"] = _serialize_texture_transform_uv1(material); + Dictionary extensions = _serialize_texture_transform_uv1(material); + if (!extensions.is_empty()) { + mrt["extensions"] = extensions; + state->use_khr_texture_transform = true; + } mr["metallicRoughnessTexture"] = mrt; } } @@ -3476,7 +3476,7 @@ Error GLTFDocument::_serialize_materials(Ref<GLTFState> state) { img->set_pixel(x, y, c); } } - tex->create_from_image(img); + tex->set_image(img); } } } @@ -3784,13 +3784,8 @@ void GLTFDocument::spec_gloss_to_rough_metal(Ref<GLTFSpecGloss> r_spec_gloss, Re } rm_img->generate_mipmaps(); r_spec_gloss->diffuse_img->generate_mipmaps(); - Ref<ImageTexture> diffuse_image_texture; - diffuse_image_texture.instantiate(); - diffuse_image_texture->create_from_image(r_spec_gloss->diffuse_img); - p_material->set_texture(BaseMaterial3D::TEXTURE_ALBEDO, diffuse_image_texture); - Ref<ImageTexture> rm_image_texture; - rm_image_texture.instantiate(); - rm_image_texture->create_from_image(rm_img); + p_material->set_texture(BaseMaterial3D::TEXTURE_ALBEDO, ImageTexture::create_from_image(r_spec_gloss->diffuse_img)); + Ref<ImageTexture> rm_image_texture = ImageTexture::create_from_image(rm_img); if (has_roughness) { p_material->set_texture(BaseMaterial3D::TEXTURE_ROUGHNESS, rm_image_texture); p_material->set_roughness_texture_channel(BaseMaterial3D::TEXTURE_CHANNEL_GREEN); @@ -4535,6 +4530,9 @@ void GLTFDocument::_remove_duplicate_skins(Ref<GLTFState> state) { } Error GLTFDocument::_serialize_lights(Ref<GLTFState> state) { + if (state->lights.is_empty()) { + return OK; + } Array lights; for (GLTFLightIndex i = 0; i < state->lights.size(); i++) { Dictionary d; @@ -4561,10 +4559,6 @@ Error GLTFDocument::_serialize_lights(Ref<GLTFState> state) { lights.push_back(d); } - if (!state->lights.size()) { - return OK; - } - Dictionary extensions; if (state->json.has("extensions")) { extensions = state->json["extensions"]; @@ -5176,19 +5170,16 @@ Node3D *GLTFDocument::_generate_light(Ref<GLTFState> state, const GLTFNodeIndex } const float range = CLAMP(l->range, 0, 4096); - // Doubling the range will double the effective brightness, so we need double attenuation (half brightness). - // We want to have double intensity give double brightness, so we need half the attenuation. - const float attenuation = range / (intensity * 2048); if (l->light_type == "point") { OmniLight3D *light = memnew(OmniLight3D); - light->set_param(OmniLight3D::PARAM_ATTENUATION, attenuation); + light->set_param(OmniLight3D::PARAM_ENERGY, intensity); light->set_param(OmniLight3D::PARAM_RANGE, range); light->set_color(l->color); return light; } if (l->light_type == "spot") { SpotLight3D *light = memnew(SpotLight3D); - light->set_param(SpotLight3D::PARAM_ATTENUATION, attenuation); + light->set_param(SpotLight3D::PARAM_ENERGY, intensity); light->set_param(SpotLight3D::PARAM_RANGE, range); light->set_param(SpotLight3D::PARAM_SPOT_ANGLE, Math::rad2deg(l->outer_cone_angle)); light->set_color(l->color); @@ -5227,7 +5218,7 @@ GLTFCameraIndex GLTFDocument::_convert_camera(Ref<GLTFState> state, Camera3D *p_ Ref<GLTFCamera> c; c.instantiate(); - if (p_camera->get_projection() == Camera3D::Projection::PROJECTION_PERSPECTIVE) { + if (p_camera->get_projection() == Camera3D::ProjectionType::PROJECTION_PERSPECTIVE) { c->set_perspective(true); } c->set_fov_size(p_camera->get_fov()); @@ -5253,14 +5244,12 @@ GLTFLightIndex GLTFDocument::_convert_light(Ref<GLTFState> state, Light3D *p_lig l->light_type = "point"; OmniLight3D *light = cast_to<OmniLight3D>(p_light); l->range = light->get_param(OmniLight3D::PARAM_RANGE); - float attenuation = p_light->get_param(OmniLight3D::PARAM_ATTENUATION); - l->intensity = l->range / (attenuation * 2048); + l->intensity = light->get_param(OmniLight3D::PARAM_ENERGY); } else if (cast_to<SpotLight3D>(p_light)) { l->light_type = "spot"; SpotLight3D *light = cast_to<SpotLight3D>(p_light); l->range = light->get_param(SpotLight3D::PARAM_RANGE); - float attenuation = light->get_param(SpotLight3D::PARAM_ATTENUATION); - l->intensity = l->range / (attenuation * 2048); + l->intensity = light->get_param(SpotLight3D::PARAM_ENERGY); l->outer_cone_angle = Math::deg2rad(light->get_param(SpotLight3D::PARAM_SPOT_ANGLE)); // This equation is the inverse of the import equation (which has a desmos link). @@ -6666,45 +6655,48 @@ Error GLTFDocument::_parse(Ref<GLTFState> state, String p_path, Ref<FileAccess> return OK; } -Dictionary GLTFDocument::_serialize_texture_transform_uv2(Ref<BaseMaterial3D> p_material) { - Dictionary extension; - Ref<BaseMaterial3D> mat = p_material; - if (mat.is_valid()) { - Dictionary texture_transform; +Dictionary _serialize_texture_transform_uv(Vector2 p_offset, Vector2 p_scale) { + Dictionary texture_transform; + bool is_offset = p_offset != Vector2(0.0, 0.0); + if (is_offset) { Array offset; offset.resize(2); - offset[0] = mat->get_uv2_offset().x; - offset[1] = mat->get_uv2_offset().y; + offset[0] = p_offset.x; + offset[1] = p_offset.y; texture_transform["offset"] = offset; + } + bool is_scaled = p_scale != Vector2(1.0, 1.0); + if (is_scaled) { Array scale; scale.resize(2); - scale[0] = mat->get_uv2_scale().x; - scale[1] = mat->get_uv2_scale().y; + scale[0] = p_scale.x; + scale[1] = p_scale.y; texture_transform["scale"] = scale; - // Godot doesn't support texture rotation + } + Dictionary extension; + // Note: Godot doesn't support texture rotation. + if (is_offset || is_scaled) { extension["KHR_texture_transform"] = texture_transform; } return extension; } Dictionary GLTFDocument::_serialize_texture_transform_uv1(Ref<BaseMaterial3D> p_material) { - Dictionary extension; if (p_material.is_valid()) { - Dictionary texture_transform; - Array offset; - offset.resize(2); - offset[0] = p_material->get_uv1_offset().x; - offset[1] = p_material->get_uv1_offset().y; - texture_transform["offset"] = offset; - Array scale; - scale.resize(2); - scale[0] = p_material->get_uv1_scale().x; - scale[1] = p_material->get_uv1_scale().y; - texture_transform["scale"] = scale; - // Godot doesn't support texture rotation - extension["KHR_texture_transform"] = texture_transform; + Vector3 offset = p_material->get_uv1_offset(); + Vector3 scale = p_material->get_uv1_scale(); + return _serialize_texture_transform_uv(Vector2(offset.x, offset.y), Vector2(scale.x, scale.y)); } - return extension; + return Dictionary(); +} + +Dictionary GLTFDocument::_serialize_texture_transform_uv2(Ref<BaseMaterial3D> p_material) { + if (p_material.is_valid()) { + Vector3 offset = p_material->get_uv2_offset(); + Vector3 scale = p_material->get_uv2_scale(); + return _serialize_texture_transform_uv(Vector2(offset.x, offset.y), Vector2(scale.x, scale.y)); + } + return Dictionary(); } Error GLTFDocument::_serialize_version(Ref<GLTFState> state) { @@ -6944,15 +6936,6 @@ Error GLTFDocument::append_from_scene(Node *p_node, Ref<GLTFState> state, uint32 state->use_named_skin_binds = p_flags & GLTF_IMPORT_USE_NAMED_SKIN_BINDS; state->discard_meshes_and_materials = p_flags & GLTF_IMPORT_DISCARD_MESHES_AND_MATERIALS; - _convert_scene_node(state, p_node, -1, -1); - if (!state->buffers.size()) { - state->buffers.push_back(Vector<uint8_t>()); - } - for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) { - Ref<GLTFDocumentExtension> ext = document_extensions[ext_i]; - ERR_CONTINUE(ext.is_null()); - } - for (int32_t ext_i = 0; ext_i < document_extensions.size(); ext_i++) { Ref<GLTFDocumentExtension> ext = document_extensions[ext_i]; ERR_CONTINUE(ext.is_null()); @@ -6963,7 +6946,6 @@ Error GLTFDocument::append_from_scene(Node *p_node, Ref<GLTFState> state, uint32 if (!state->buffers.size()) { state->buffers.push_back(Vector<uint8_t>()); } - return OK; } diff --git a/modules/gltf/gltf_document.h b/modules/gltf/gltf_document.h index 2f61210ff9..36a2f94a4e 100644 --- a/modules/gltf/gltf_document.h +++ b/modules/gltf/gltf_document.h @@ -31,48 +31,19 @@ #ifndef GLTF_DOCUMENT_H #define GLTF_DOCUMENT_H -#include "gltf_animation.h" +#include "gltf_defines.h" +#include "structures/gltf_animation.h" #include "scene/3d/bone_attachment_3d.h" #include "scene/3d/importer_mesh_instance_3d.h" -#include "scene/3d/light_3d.h" #include "scene/3d/mesh_instance_3d.h" #include "scene/animation/animation_player.h" #include "scene/resources/material.h" #include "modules/modules_enabled.gen.h" // For csg, gridmap. -#include <cstdint> - -class GLTFState; -class GLTFSkin; -class GLTFNode; -class GLTFSpecGloss; -class GLTFSkeleton; -class CSGShape3D; -class GridMap; -class MultiMeshInstance3D; -class GLTFDocumentExtension; - -using GLTFAccessorIndex = int; -using GLTFAnimationIndex = int; -using GLTFBufferIndex = int; -using GLTFBufferViewIndex = int; -using GLTFCameraIndex = int; -using GLTFImageIndex = int; -using GLTFMaterialIndex = int; -using GLTFMeshIndex = int; -using GLTFLightIndex = int; -using GLTFNodeIndex = int; -using GLTFSkeletonIndex = int; -using GLTFSkinIndex = int; -using GLTFTextureIndex = int; - class GLTFDocument : public Resource { GDCLASS(GLTFDocument, Resource); - friend class GLTFState; - friend class GLTFSkin; - friend class GLTFSkeleton; TypedArray<GLTFDocumentExtension> document_extensions; private: @@ -81,15 +52,6 @@ private: public: GLTFDocument(); const int32_t JOINT_GROUP_SIZE = 4; - enum GLTFType { - TYPE_SCALAR, - TYPE_VEC2, - TYPE_VEC3, - TYPE_VEC4, - TYPE_MAT2, - TYPE_MAT3, - TYPE_MAT4, - }; enum { ARRAY_BUFFER = 34962, @@ -118,58 +80,6 @@ public: TypedArray<GLTFDocumentExtension> get_extensions() const; private: - template <class T> - static Array to_array(const Vector<T> &p_inp) { - Array ret; - for (int i = 0; i < p_inp.size(); i++) { - ret.push_back(p_inp[i]); - } - return ret; - } - - template <class T> - static Array to_array(const HashSet<T> &p_inp) { - Array ret; - typename HashSet<T>::Iterator elem = p_inp.begin(); - while (elem) { - ret.push_back(*elem); - ++elem; - } - return ret; - } - - template <class T> - static void set_from_array(Vector<T> &r_out, const Array &p_inp) { - r_out.clear(); - for (int i = 0; i < p_inp.size(); i++) { - r_out.push_back(p_inp[i]); - } - } - - template <class T> - static void set_from_array(HashSet<T> &r_out, const Array &p_inp) { - r_out.clear(); - for (int i = 0; i < p_inp.size(); i++) { - r_out.insert(p_inp[i]); - } - } - template <class K, class V> - static Dictionary to_dict(const HashMap<K, V> &p_inp) { - Dictionary ret; - for (const KeyValue<K, V> &E : p_inp) { - ret[E.key] = E.value; - } - return ret; - } - - template <class K, class V> - static void set_from_dict(HashMap<K, V> &r_out, const Dictionary &p_inp) { - r_out.clear(); - Array keys = p_inp.keys(); - for (int i = 0; i < keys.size(); i++) { - r_out[keys[i]] = p_inp[keys[i]]; - } - } void _build_parent_hierachy(Ref<GLTFState> state); double _filter_number(double p_float); String _get_component_type_name(const uint32_t p_component); @@ -177,7 +87,7 @@ private: Error _parse_scenes(Ref<GLTFState> state); Error _parse_nodes(Ref<GLTFState> state); String _get_type_name(const GLTFType p_component); - String _get_accessor_type_name(const GLTFDocument::GLTFType p_type); + String _get_accessor_type_name(const GLTFType p_type); String _gen_unique_name(Ref<GLTFState> state, const String &p_name); String _sanitize_animation_name(const String &name); String _gen_unique_animation_name(Ref<GLTFState> state, const String &p_name); diff --git a/modules/gltf/gltf_document_extension.h b/modules/gltf/gltf_document_extension.h index 556f79e887..0ef9109584 100644 --- a/modules/gltf/gltf_document_extension.h +++ b/modules/gltf/gltf_document_extension.h @@ -31,9 +31,8 @@ #ifndef GLTF_DOCUMENT_EXTENSION_H #define GLTF_DOCUMENT_EXTENSION_H -#include "gltf_accessor.h" -#include "gltf_node.h" #include "gltf_state.h" +#include "structures/gltf_node.h" class GLTFDocumentExtension : public Resource { GDCLASS(GLTFDocumentExtension, Resource); diff --git a/modules/gltf/gltf_document_extension_convert_importer_mesh.h b/modules/gltf/gltf_document_extension_convert_importer_mesh.h index 4c9e42a00f..00e664e73f 100644 --- a/modules/gltf/gltf_document_extension_convert_importer_mesh.h +++ b/modules/gltf/gltf_document_extension_convert_importer_mesh.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GLTF_EXTENSION_EDITOR_H -#define GLTF_EXTENSION_EDITOR_H +#ifndef GLTF_DOCUMENT_EXTENSION_CONVERT_IMPORTER_MESH_H +#define GLTF_DOCUMENT_EXTENSION_CONVERT_IMPORTER_MESH_H #include "gltf_document_extension.h" @@ -37,8 +37,6 @@ #include "scene/3d/mesh_instance_3d.h" #include "scene/resources/importer_mesh.h" -class GLTFDocumentExtension; -class GLTFDocument; class GLTFDocumentExtensionConvertImporterMesh : public GLTFDocumentExtension { GDCLASS(GLTFDocumentExtensionConvertImporterMesh, GLTFDocumentExtension); @@ -48,4 +46,5 @@ protected: public: Error import_post(Ref<GLTFState> p_state, Node *p_root) override; }; -#endif // GLTF_EXTENSION_EDITOR_H + +#endif // GLTF_DOCUMENT_EXTENSION_CONVERT_IMPORTER_MESH_H diff --git a/modules/gltf/gltf_state.cpp b/modules/gltf/gltf_state.cpp index 989fa476c2..a5f7bcf9d6 100644 --- a/modules/gltf/gltf_state.cpp +++ b/modules/gltf/gltf_state.cpp @@ -150,51 +150,51 @@ void GLTFState::set_use_named_skin_binds(bool p_use_named_skin_binds) { } Array GLTFState::get_nodes() { - return GLTFDocument::to_array(nodes); + return GLTFTemplateConvert::to_array(nodes); } void GLTFState::set_nodes(Array p_nodes) { - GLTFDocument::set_from_array(nodes, p_nodes); + GLTFTemplateConvert::set_from_array(nodes, p_nodes); } Array GLTFState::get_buffers() { - return GLTFDocument::to_array(buffers); + return GLTFTemplateConvert::to_array(buffers); } void GLTFState::set_buffers(Array p_buffers) { - GLTFDocument::set_from_array(buffers, p_buffers); + GLTFTemplateConvert::set_from_array(buffers, p_buffers); } Array GLTFState::get_buffer_views() { - return GLTFDocument::to_array(buffer_views); + return GLTFTemplateConvert::to_array(buffer_views); } void GLTFState::set_buffer_views(Array p_buffer_views) { - GLTFDocument::set_from_array(buffer_views, p_buffer_views); + GLTFTemplateConvert::set_from_array(buffer_views, p_buffer_views); } Array GLTFState::get_accessors() { - return GLTFDocument::to_array(accessors); + return GLTFTemplateConvert::to_array(accessors); } void GLTFState::set_accessors(Array p_accessors) { - GLTFDocument::set_from_array(accessors, p_accessors); + GLTFTemplateConvert::set_from_array(accessors, p_accessors); } Array GLTFState::get_meshes() { - return GLTFDocument::to_array(meshes); + return GLTFTemplateConvert::to_array(meshes); } void GLTFState::set_meshes(Array p_meshes) { - GLTFDocument::set_from_array(meshes, p_meshes); + GLTFTemplateConvert::set_from_array(meshes, p_meshes); } Array GLTFState::get_materials() { - return GLTFDocument::to_array(materials); + return GLTFTemplateConvert::to_array(materials); } void GLTFState::set_materials(Array p_materials) { - GLTFDocument::set_from_array(materials, p_materials); + GLTFTemplateConvert::set_from_array(materials, p_materials); } String GLTFState::get_scene_name() { @@ -206,91 +206,91 @@ void GLTFState::set_scene_name(String p_scene_name) { } Array GLTFState::get_root_nodes() { - return GLTFDocument::to_array(root_nodes); + return GLTFTemplateConvert::to_array(root_nodes); } void GLTFState::set_root_nodes(Array p_root_nodes) { - GLTFDocument::set_from_array(root_nodes, p_root_nodes); + GLTFTemplateConvert::set_from_array(root_nodes, p_root_nodes); } Array GLTFState::get_textures() { - return GLTFDocument::to_array(textures); + return GLTFTemplateConvert::to_array(textures); } void GLTFState::set_textures(Array p_textures) { - GLTFDocument::set_from_array(textures, p_textures); + GLTFTemplateConvert::set_from_array(textures, p_textures); } Array GLTFState::get_images() { - return GLTFDocument::to_array(images); + return GLTFTemplateConvert::to_array(images); } void GLTFState::set_images(Array p_images) { - GLTFDocument::set_from_array(images, p_images); + GLTFTemplateConvert::set_from_array(images, p_images); } Array GLTFState::get_skins() { - return GLTFDocument::to_array(skins); + return GLTFTemplateConvert::to_array(skins); } void GLTFState::set_skins(Array p_skins) { - GLTFDocument::set_from_array(skins, p_skins); + GLTFTemplateConvert::set_from_array(skins, p_skins); } Array GLTFState::get_cameras() { - return GLTFDocument::to_array(cameras); + return GLTFTemplateConvert::to_array(cameras); } void GLTFState::set_cameras(Array p_cameras) { - GLTFDocument::set_from_array(cameras, p_cameras); + GLTFTemplateConvert::set_from_array(cameras, p_cameras); } Array GLTFState::get_lights() { - return GLTFDocument::to_array(lights); + return GLTFTemplateConvert::to_array(lights); } void GLTFState::set_lights(Array p_lights) { - GLTFDocument::set_from_array(lights, p_lights); + GLTFTemplateConvert::set_from_array(lights, p_lights); } Array GLTFState::get_unique_names() { - return GLTFDocument::to_array(unique_names); + return GLTFTemplateConvert::to_array(unique_names); } void GLTFState::set_unique_names(Array p_unique_names) { - GLTFDocument::set_from_array(unique_names, p_unique_names); + GLTFTemplateConvert::set_from_array(unique_names, p_unique_names); } Array GLTFState::get_unique_animation_names() { - return GLTFDocument::to_array(unique_animation_names); + return GLTFTemplateConvert::to_array(unique_animation_names); } void GLTFState::set_unique_animation_names(Array p_unique_animation_names) { - GLTFDocument::set_from_array(unique_animation_names, p_unique_animation_names); + GLTFTemplateConvert::set_from_array(unique_animation_names, p_unique_animation_names); } Array GLTFState::get_skeletons() { - return GLTFDocument::to_array(skeletons); + return GLTFTemplateConvert::to_array(skeletons); } void GLTFState::set_skeletons(Array p_skeletons) { - GLTFDocument::set_from_array(skeletons, p_skeletons); + GLTFTemplateConvert::set_from_array(skeletons, p_skeletons); } Dictionary GLTFState::get_skeleton_to_node() { - return GLTFDocument::to_dict(skeleton_to_node); + return GLTFTemplateConvert::to_dict(skeleton_to_node); } void GLTFState::set_skeleton_to_node(Dictionary p_skeleton_to_node) { - GLTFDocument::set_from_dict(skeleton_to_node, p_skeleton_to_node); + GLTFTemplateConvert::set_from_dict(skeleton_to_node, p_skeleton_to_node); } Array GLTFState::get_animations() { - return GLTFDocument::to_array(animations); + return GLTFTemplateConvert::to_array(animations); } void GLTFState::set_animations(Array p_animations) { - GLTFDocument::set_from_array(animations, p_animations); + GLTFTemplateConvert::set_from_array(animations, p_animations); } Node *GLTFState::get_scene_node(GLTFNodeIndex idx) { diff --git a/modules/gltf/gltf_state.h b/modules/gltf/gltf_state.h index 2fdef19038..d2a4948f06 100644 --- a/modules/gltf/gltf_state.h +++ b/modules/gltf/gltf_state.h @@ -31,18 +31,17 @@ #ifndef GLTF_STATE_H #define GLTF_STATE_H -#include "gltf_accessor.h" -#include "gltf_animation.h" -#include "gltf_buffer_view.h" -#include "gltf_camera.h" -#include "gltf_document.h" -#include "gltf_document_extension.h" -#include "gltf_light.h" -#include "gltf_mesh.h" -#include "gltf_node.h" -#include "gltf_skeleton.h" -#include "gltf_skin.h" -#include "gltf_texture.h" +#include "extensions/gltf_light.h" +#include "gltf_template_convert.h" +#include "structures/gltf_accessor.h" +#include "structures/gltf_animation.h" +#include "structures/gltf_buffer_view.h" +#include "structures/gltf_camera.h" +#include "structures/gltf_mesh.h" +#include "structures/gltf_node.h" +#include "structures/gltf_skeleton.h" +#include "structures/gltf_skin.h" +#include "structures/gltf_texture.h" #include "core/templates/rb_map.h" #include "scene/animation/animation_player.h" @@ -60,6 +59,7 @@ class GLTFState : public Resource { Vector<uint8_t> glb_data; bool use_named_skin_binds = false; + bool use_khr_texture_transform = false; bool discard_meshes_and_materials = false; Vector<Ref<GLTFNode>> nodes; @@ -192,4 +192,5 @@ public: // this->material_cache = p_material_cache; //} }; + #endif // GLTF_STATE_H diff --git a/modules/gltf/gltf_template_convert.h b/modules/gltf/gltf_template_convert.h new file mode 100644 index 0000000000..c915d3deb0 --- /dev/null +++ b/modules/gltf/gltf_template_convert.h @@ -0,0 +1,94 @@ +/*************************************************************************/ +/* gltf_template_convert.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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. */ +/*************************************************************************/ + +#ifndef GLTF_TEMPLATE_CONVERT_H +#define GLTF_TEMPLATE_CONVERT_H + +#include "core/templates/hash_set.h" +#include "core/variant/array.h" +#include "core/variant/dictionary.h" + +namespace GLTFTemplateConvert { +template <class T> +static Array to_array(const Vector<T> &p_inp) { + Array ret; + for (int i = 0; i < p_inp.size(); i++) { + ret.push_back(p_inp[i]); + } + return ret; +} + +template <class T> +static Array to_array(const HashSet<T> &p_inp) { + Array ret; + typename HashSet<T>::Iterator elem = p_inp.begin(); + while (elem) { + ret.push_back(*elem); + ++elem; + } + return ret; +} + +template <class T> +static void set_from_array(Vector<T> &r_out, const Array &p_inp) { + r_out.clear(); + for (int i = 0; i < p_inp.size(); i++) { + r_out.push_back(p_inp[i]); + } +} + +template <class T> +static void set_from_array(HashSet<T> &r_out, const Array &p_inp) { + r_out.clear(); + for (int i = 0; i < p_inp.size(); i++) { + r_out.insert(p_inp[i]); + } +} + +template <class K, class V> +static Dictionary to_dict(const HashMap<K, V> &p_inp) { + Dictionary ret; + for (const KeyValue<K, V> &E : p_inp) { + ret[E.key] = E.value; + } + return ret; +} + +template <class K, class V> +static void set_from_dict(HashMap<K, V> &r_out, const Dictionary &p_inp) { + r_out.clear(); + Array keys = p_inp.keys(); + for (int i = 0; i < keys.size(); i++) { + r_out[keys[i]] = p_inp[keys[i]]; + } +} +} //namespace GLTFTemplateConvert + +#endif // GLTF_TEMPLATE_CONVERT_H diff --git a/modules/gltf/register_types.cpp b/modules/gltf/register_types.cpp index b8bac79584..1e1204aa57 100644 --- a/modules/gltf/register_types.cpp +++ b/modules/gltf/register_types.cpp @@ -32,21 +32,21 @@ #ifndef _3D_DISABLED -#include "gltf_accessor.h" -#include "gltf_animation.h" -#include "gltf_buffer_view.h" -#include "gltf_camera.h" +#include "extensions/gltf_light.h" +#include "extensions/gltf_spec_gloss.h" #include "gltf_document.h" #include "gltf_document_extension.h" #include "gltf_document_extension_convert_importer_mesh.h" -#include "gltf_light.h" -#include "gltf_mesh.h" -#include "gltf_node.h" -#include "gltf_skeleton.h" -#include "gltf_skin.h" -#include "gltf_spec_gloss.h" #include "gltf_state.h" -#include "gltf_texture.h" +#include "structures/gltf_accessor.h" +#include "structures/gltf_animation.h" +#include "structures/gltf_buffer_view.h" +#include "structures/gltf_camera.h" +#include "structures/gltf_mesh.h" +#include "structures/gltf_node.h" +#include "structures/gltf_skeleton.h" +#include "structures/gltf_skin.h" +#include "structures/gltf_texture.h" #ifdef TOOLS_ENABLED #include "core/config/project_settings.h" diff --git a/modules/gltf/gltf_accessor.cpp b/modules/gltf/structures/gltf_accessor.cpp index 1daf2f90a7..1b8911fe72 100644 --- a/modules/gltf/gltf_accessor.cpp +++ b/modules/gltf/structures/gltf_accessor.cpp @@ -30,8 +30,6 @@ #include "gltf_accessor.h" -#include "gltf_document_extension.h" - void GLTFAccessor::_bind_methods() { ClassDB::bind_method(D_METHOD("get_buffer_view"), &GLTFAccessor::get_buffer_view); ClassDB::bind_method(D_METHOD("set_buffer_view", "buffer_view"), &GLTFAccessor::set_buffer_view); @@ -67,7 +65,7 @@ void GLTFAccessor::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "component_type"), "set_component_type", "get_component_type"); // int ADD_PROPERTY(PropertyInfo(Variant::BOOL, "normalized"), "set_normalized", "get_normalized"); // bool ADD_PROPERTY(PropertyInfo(Variant::INT, "count"), "set_count", "get_count"); // int - ADD_PROPERTY(PropertyInfo(Variant::INT, "type"), "set_type", "get_type"); // GLTFDocument::GLTFType + ADD_PROPERTY(PropertyInfo(Variant::INT, "type"), "set_type", "get_type"); // GLTFType ADD_PROPERTY(PropertyInfo(Variant::PACKED_FLOAT64_ARRAY, "min"), "set_min", "get_min"); // Vector<real_t> ADD_PROPERTY(PropertyInfo(Variant::PACKED_FLOAT64_ARRAY, "max"), "set_max", "get_max"); // Vector<real_t> ADD_PROPERTY(PropertyInfo(Variant::INT, "sparse_count"), "set_sparse_count", "get_sparse_count"); // int @@ -123,7 +121,7 @@ int GLTFAccessor::get_type() { } void GLTFAccessor::set_type(int p_type) { - type = (GLTFDocument::GLTFType)p_type; // TODO: Register enum + type = (GLTFType)p_type; // TODO: Register enum } Vector<double> GLTFAccessor::get_min() { diff --git a/modules/gltf/gltf_accessor.h b/modules/gltf/structures/gltf_accessor.h index f412dc2c7f..bfb71d57fe 100644 --- a/modules/gltf/gltf_accessor.h +++ b/modules/gltf/structures/gltf_accessor.h @@ -33,7 +33,7 @@ #include "core/io/resource.h" -#include "gltf_document.h" +#include "../gltf_defines.h" struct GLTFAccessor : public Resource { GDCLASS(GLTFAccessor, Resource); @@ -45,7 +45,7 @@ private: int component_type = 0; bool normalized = false; int count = 0; - GLTFDocument::GLTFType type = GLTFDocument::TYPE_SCALAR; + GLTFType type = GLTFType::TYPE_SCALAR; Vector<double> min; Vector<double> max; int sparse_count = 0; @@ -101,4 +101,5 @@ public: int get_sparse_values_byte_offset(); void set_sparse_values_byte_offset(int p_sparse_values_byte_offset); }; + #endif // GLTF_ACCESSOR_H diff --git a/modules/gltf/gltf_animation.cpp b/modules/gltf/structures/gltf_animation.cpp index e598c870ab..e598c870ab 100644 --- a/modules/gltf/gltf_animation.cpp +++ b/modules/gltf/structures/gltf_animation.cpp diff --git a/modules/gltf/gltf_animation.h b/modules/gltf/structures/gltf_animation.h index 8688ddb937..3777f579f6 100644 --- a/modules/gltf/gltf_animation.h +++ b/modules/gltf/structures/gltf_animation.h @@ -71,4 +71,5 @@ private: bool loop = false; HashMap<int, Track> tracks; }; + #endif // GLTF_ANIMATION_H diff --git a/modules/gltf/gltf_buffer_view.cpp b/modules/gltf/structures/gltf_buffer_view.cpp index fc467367c6..ba19ed8628 100644 --- a/modules/gltf/gltf_buffer_view.cpp +++ b/modules/gltf/structures/gltf_buffer_view.cpp @@ -30,7 +30,7 @@ #include "gltf_buffer_view.h" -#include "gltf_document_extension.h" +#include "../gltf_document_extension.h" void GLTFBufferView::_bind_methods() { ClassDB::bind_method(D_METHOD("get_buffer"), &GLTFBufferView::get_buffer); diff --git a/modules/gltf/gltf_buffer_view.h b/modules/gltf/structures/gltf_buffer_view.h index 560d56f35c..b1f500de25 100644 --- a/modules/gltf/gltf_buffer_view.h +++ b/modules/gltf/structures/gltf_buffer_view.h @@ -31,8 +31,8 @@ #ifndef GLTF_BUFFER_VIEW_H #define GLTF_BUFFER_VIEW_H +#include "../gltf_defines.h" #include "core/io/resource.h" -#include "gltf_document.h" class GLTFBufferView : public Resource { GDCLASS(GLTFBufferView, Resource); @@ -65,4 +65,5 @@ public: void set_indices(bool p_indices); // matrices need to be transformed to this }; + #endif // GLTF_BUFFER_VIEW_H diff --git a/modules/gltf/gltf_camera.cpp b/modules/gltf/structures/gltf_camera.cpp index f3ea6a1c4c..f3ea6a1c4c 100644 --- a/modules/gltf/gltf_camera.cpp +++ b/modules/gltf/structures/gltf_camera.cpp diff --git a/modules/gltf/gltf_camera.h b/modules/gltf/structures/gltf_camera.h index c696d4cc6b..b7df741825 100644 --- a/modules/gltf/gltf_camera.h +++ b/modules/gltf/structures/gltf_camera.h @@ -55,4 +55,5 @@ public: float get_depth_near() const { return depth_near; } void set_depth_near(float p_val) { depth_near = p_val; } }; + #endif // GLTF_CAMERA_H diff --git a/modules/gltf/gltf_mesh.cpp b/modules/gltf/structures/gltf_mesh.cpp index 3add8304b1..3add8304b1 100644 --- a/modules/gltf/gltf_mesh.cpp +++ b/modules/gltf/structures/gltf_mesh.cpp diff --git a/modules/gltf/gltf_mesh.h b/modules/gltf/structures/gltf_mesh.h index dc26120b48..dc26120b48 100644 --- a/modules/gltf/gltf_mesh.h +++ b/modules/gltf/structures/gltf_mesh.h diff --git a/modules/gltf/gltf_node.cpp b/modules/gltf/structures/gltf_node.cpp index 86280603fa..86280603fa 100644 --- a/modules/gltf/gltf_node.cpp +++ b/modules/gltf/structures/gltf_node.cpp diff --git a/modules/gltf/gltf_node.h b/modules/gltf/structures/gltf_node.h index 929ad3eca0..1a57ea32e2 100644 --- a/modules/gltf/gltf_node.h +++ b/modules/gltf/structures/gltf_node.h @@ -31,8 +31,8 @@ #ifndef GLTF_NODE_H #define GLTF_NODE_H +#include "../gltf_defines.h" #include "core/io/resource.h" -#include "gltf_document.h" class GLTFNode : public Resource { GDCLASS(GLTFNode, Resource); @@ -97,4 +97,5 @@ public: GLTFLightIndex get_light(); void set_light(GLTFLightIndex p_light); }; + #endif // GLTF_NODE_H diff --git a/modules/gltf/gltf_skeleton.cpp b/modules/gltf/structures/gltf_skeleton.cpp index b813f39a27..90a6b0f50f 100644 --- a/modules/gltf/gltf_skeleton.cpp +++ b/modules/gltf/structures/gltf_skeleton.cpp @@ -30,6 +30,9 @@ #include "gltf_skeleton.h" +#include "../gltf_template_convert.h" +#include "scene/3d/bone_attachment_3d.h" + void GLTFSkeleton::_bind_methods() { ClassDB::bind_method(D_METHOD("get_joints"), &GLTFSkeleton::get_joints); ClassDB::bind_method(D_METHOD("set_joints", "joints"), &GLTFSkeleton::set_joints); @@ -70,19 +73,19 @@ Skeleton3D *GLTFSkeleton::get_godot_skeleton() { } Array GLTFSkeleton::get_unique_names() { - return GLTFDocument::to_array(unique_names); + return GLTFTemplateConvert::to_array(unique_names); } void GLTFSkeleton::set_unique_names(Array p_unique_names) { - GLTFDocument::set_from_array(unique_names, p_unique_names); + GLTFTemplateConvert::set_from_array(unique_names, p_unique_names); } Dictionary GLTFSkeleton::get_godot_bone_node() { - return GLTFDocument::to_dict(godot_bone_node); + return GLTFTemplateConvert::to_dict(godot_bone_node); } void GLTFSkeleton::set_godot_bone_node(Dictionary p_indict) { - GLTFDocument::set_from_dict(godot_bone_node, p_indict); + GLTFTemplateConvert::set_from_dict(godot_bone_node, p_indict); } BoneAttachment3D *GLTFSkeleton::get_bone_attachment(int idx) { diff --git a/modules/gltf/gltf_skeleton.h b/modules/gltf/structures/gltf_skeleton.h index 92ee6e6234..db88623213 100644 --- a/modules/gltf/gltf_skeleton.h +++ b/modules/gltf/structures/gltf_skeleton.h @@ -31,8 +31,8 @@ #ifndef GLTF_SKELETON_H #define GLTF_SKELETON_H +#include "../gltf_defines.h" #include "core/io/resource.h" -#include "gltf_document.h" class GLTFSkeleton : public Resource { GDCLASS(GLTFSkeleton, Resource); @@ -98,4 +98,5 @@ public: int32_t get_bone_attachment_count(); }; + #endif // GLTF_SKELETON_H diff --git a/modules/gltf/gltf_skin.cpp b/modules/gltf/structures/gltf_skin.cpp index e8005aa0c1..2e46ee3be2 100644 --- a/modules/gltf/gltf_skin.cpp +++ b/modules/gltf/structures/gltf_skin.cpp @@ -30,6 +30,9 @@ #include "gltf_skin.h" +#include "../gltf_template_convert.h" +#include "scene/resources/skin.h" + void GLTFSkin::_bind_methods() { ClassDB::bind_method(D_METHOD("get_skin_root"), &GLTFSkin::get_skin_root); ClassDB::bind_method(D_METHOD("set_skin_root", "skin_root"), &GLTFSkin::set_skin_root); @@ -81,11 +84,11 @@ void GLTFSkin::set_joints_original(Vector<GLTFNodeIndex> p_joints_original) { } Array GLTFSkin::get_inverse_binds() { - return GLTFDocument::to_array(inverse_binds); + return GLTFTemplateConvert::to_array(inverse_binds); } void GLTFSkin::set_inverse_binds(Array p_inverse_binds) { - GLTFDocument::set_from_array(inverse_binds, p_inverse_binds); + GLTFTemplateConvert::set_from_array(inverse_binds, p_inverse_binds); } Vector<GLTFNodeIndex> GLTFSkin::get_joints() { @@ -121,11 +124,11 @@ void GLTFSkin::set_skeleton(int p_skeleton) { } Dictionary GLTFSkin::get_joint_i_to_bone_i() { - return GLTFDocument::to_dict(joint_i_to_bone_i); + return GLTFTemplateConvert::to_dict(joint_i_to_bone_i); } void GLTFSkin::set_joint_i_to_bone_i(Dictionary p_joint_i_to_bone_i) { - GLTFDocument::set_from_dict(joint_i_to_bone_i, p_joint_i_to_bone_i); + GLTFTemplateConvert::set_from_dict(joint_i_to_bone_i, p_joint_i_to_bone_i); } Dictionary GLTFSkin::get_joint_i_to_name() { diff --git a/modules/gltf/gltf_skin.h b/modules/gltf/structures/gltf_skin.h index d946324756..59b6a300ac 100644 --- a/modules/gltf/gltf_skin.h +++ b/modules/gltf/structures/gltf_skin.h @@ -31,8 +31,8 @@ #ifndef GLTF_SKIN_H #define GLTF_SKIN_H +#include "../gltf_defines.h" #include "core/io/resource.h" -#include "gltf_document.h" class GLTFSkin : public Resource { GDCLASS(GLTFSkin, Resource); @@ -106,4 +106,5 @@ public: Ref<Skin> get_godot_skin(); void set_godot_skin(Ref<Skin> p_godot_skin); }; + #endif // GLTF_SKIN_H diff --git a/modules/gltf/gltf_texture.cpp b/modules/gltf/structures/gltf_texture.cpp index 2a21cb3df8..2a21cb3df8 100644 --- a/modules/gltf/gltf_texture.cpp +++ b/modules/gltf/structures/gltf_texture.cpp diff --git a/modules/gltf/gltf_texture.h b/modules/gltf/structures/gltf_texture.h index 54dd61f9a5..b1d12dddfa 100644 --- a/modules/gltf/gltf_texture.h +++ b/modules/gltf/structures/gltf_texture.h @@ -31,8 +31,8 @@ #ifndef GLTF_TEXTURE_H #define GLTF_TEXTURE_H +#include "../gltf_defines.h" #include "core/io/resource.h" -#include "gltf_document.h" class GLTFTexture : public Resource { GDCLASS(GLTFTexture, Resource); diff --git a/modules/gridmap/editor/grid_map_editor_plugin.cpp b/modules/gridmap/editor/grid_map_editor_plugin.cpp index b694c109e1..fe4edf112b 100644 --- a/modules/gridmap/editor/grid_map_editor_plugin.cpp +++ b/modules/gridmap/editor/grid_map_editor_plugin.cpp @@ -545,7 +545,7 @@ void GridMapEditor::_update_paste_indicator() { Basis rot; rot.set_orthogonal_index(paste_indicator.orientation); xf.basis = rot * xf.basis; - xf.translate((-center * node->get_cell_size()) / scale); + xf.translate_local((-center * node->get_cell_size()) / scale); RenderingServer::get_singleton()->instance_set_transform(paste_instance, node->get_global_transform() * xf); @@ -553,7 +553,7 @@ void GridMapEditor::_update_paste_indicator() { xf = Transform3D(); xf.origin = (paste_indicator.begin + (paste_indicator.current - paste_indicator.click) + center) * node->get_cell_size(); xf.basis = rot * xf.basis; - xf.translate(item.grid_offset * node->get_cell_size()); + xf.translate_local(item.grid_offset * node->get_cell_size()); Basis item_rot; item_rot.set_orthogonal_index(item.orientation); @@ -1262,7 +1262,7 @@ GridMapEditor::GridMapEditor() { info_message->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER); info_message->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART); info_message->set_custom_minimum_size(Size2(100 * EDSCALE, 0)); - info_message->set_anchors_and_offsets_preset(PRESET_WIDE, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); + info_message->set_anchors_and_offsets_preset(PRESET_FULL_RECT, PRESET_MODE_KEEP_SIZE, 8 * EDSCALE); mesh_library_palette->add_child(info_message); edit_axis = Vector3::AXIS_Y; diff --git a/modules/hdr/image_loader_hdr.h b/modules/hdr/image_loader_hdr.h index f2d53cc206..16c0816562 100644 --- a/modules/hdr/image_loader_hdr.h +++ b/modules/hdr/image_loader_hdr.h @@ -40,4 +40,4 @@ public: ImageLoaderHDR(); }; -#endif +#endif // IMAGE_LOADER_HDR_H diff --git a/modules/jpg/image_loader_jpegd.h b/modules/jpg/image_loader_jpegd.h index de9700faec..6d631446e7 100644 --- a/modules/jpg/image_loader_jpegd.h +++ b/modules/jpg/image_loader_jpegd.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef IMAGE_LOADER_JPG_H -#define IMAGE_LOADER_JPG_H +#ifndef IMAGE_LOADER_JPEGD_H +#define IMAGE_LOADER_JPEGD_H #include "core/io/image_loader.h" @@ -40,4 +40,4 @@ public: ImageLoaderJPG(); }; -#endif +#endif // IMAGE_LOADER_JPEGD_H diff --git a/modules/jsonrpc/jsonrpc.h b/modules/jsonrpc/jsonrpc.h index f57d6aef42..1d9f2771b2 100644 --- a/modules/jsonrpc/jsonrpc.h +++ b/modules/jsonrpc/jsonrpc.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GODOT_JSON_RPC_H -#define GODOT_JSON_RPC_H +#ifndef JSONRPC_H +#define JSONRPC_H #include "core/object/class_db.h" #include "core/variant/variant.h" @@ -67,4 +67,4 @@ public: VARIANT_ENUM_CAST(JSONRPC::ErrorCode); -#endif +#endif // JSONRPC_H diff --git a/modules/lightmapper_rd/SCsub b/modules/lightmapper_rd/SCsub index 5cc9d8ee8b..fe9737b36f 100644 --- a/modules/lightmapper_rd/SCsub +++ b/modules/lightmapper_rd/SCsub @@ -7,9 +7,7 @@ env_lightmapper_rd = env_modules.Clone() env_lightmapper_rd.GLSL_HEADER("lm_raster.glsl") env_lightmapper_rd.GLSL_HEADER("lm_compute.glsl") env_lightmapper_rd.GLSL_HEADER("lm_blendseams.glsl") -env_lightmapper_rd.Depends("lm_raster.glsl.gen.h", "lm_common_inc.glsl") -env_lightmapper_rd.Depends("lm_compute.glsl.gen.h", "lm_common_inc.glsl") -env_lightmapper_rd.Depends("lm_blendseams.glsl.gen.h", "lm_common_inc.glsl") +env_lightmapper_rd.Depends(Glob("*.glsl.gen.h"), ["lm_common_inc.glsl", "#glsl_builders.py"]) # Godot source files env_lightmapper_rd.add_source_files(env.modules_sources, "*.cpp") diff --git a/modules/lightmapper_rd/lightmapper_rd.cpp b/modules/lightmapper_rd/lightmapper_rd.cpp index 2ce3715bea..83ac478a97 100644 --- a/modules/lightmapper_rd/lightmapper_rd.cpp +++ b/modules/lightmapper_rd/lightmapper_rd.cpp @@ -271,8 +271,8 @@ Lightmapper::BakeError LightmapperRD::_blit_meshes_into_atlas(int p_max_texture_ mi.offset.x = best_atlas_offsets[m_i].x; mi.offset.y = best_atlas_offsets[m_i].y; mi.slice = best_atlas_offsets[m_i].z; - albedo_images.write[mi.slice]->blit_rect(mi.data.albedo_on_uv2, Rect2(Vector2(), Size2i(mi.data.albedo_on_uv2->get_width(), mi.data.albedo_on_uv2->get_height())), mi.offset); - emission_images.write[mi.slice]->blit_rect(mi.data.emission_on_uv2, Rect2(Vector2(), Size2i(mi.data.emission_on_uv2->get_width(), mi.data.emission_on_uv2->get_height())), mi.offset); + albedo_images.write[mi.slice]->blit_rect(mi.data.albedo_on_uv2, Rect2i(Vector2i(), mi.data.albedo_on_uv2->get_size()), mi.offset); + emission_images.write[mi.slice]->blit_rect(mi.data.emission_on_uv2, Rect2(Vector2i(), mi.data.emission_on_uv2->get_size()), mi.offset); } return BAKE_OK; @@ -1420,7 +1420,7 @@ LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_d img2.instantiate(); img2->create(2, 2, false, Image::FORMAT_RGBAF, s); img2->convert(Image::FORMAT_RGB8); - img->blit_rect(img2, Rect2(0, 0, 2, 2), Point2((j % 3) * 2, (j / 3) * 2)); + img->blit_rect(img2, Rect2i(0, 0, 2, 2), Point2i((j % 3) * 2, (j / 3) * 2)); } img->save_png("res://3_light_probe_" + itos(i) + ".png"); } diff --git a/modules/lightmapper_rd/lightmapper_rd.h b/modules/lightmapper_rd/lightmapper_rd.h index 8cb4b58a18..88860ad0d4 100644 --- a/modules/lightmapper_rd/lightmapper_rd.h +++ b/modules/lightmapper_rd/lightmapper_rd.h @@ -256,4 +256,4 @@ public: LightmapperRD(); }; -#endif // LIGHTMAPPER_H +#endif // LIGHTMAPPER_RD_H diff --git a/modules/lightmapper_rd/register_types.h b/modules/lightmapper_rd/register_types.h index 42e0ebbf77..9b72ff45d7 100644 --- a/modules/lightmapper_rd/register_types.h +++ b/modules/lightmapper_rd/register_types.h @@ -36,4 +36,4 @@ void initialize_lightmapper_rd_module(ModuleInitializationLevel p_level); void uninitialize_lightmapper_rd_module(ModuleInitializationLevel p_level); -#endif // XATLAS_UNWRAP_REGISTER_TYPES_H +#endif // LIGHTMAPPER_RD_REGISTER_TYPES_H diff --git a/modules/mbedtls/dtls_server_mbedtls.h b/modules/mbedtls/dtls_server_mbedtls.h index 29370062c4..a6626c9f65 100644 --- a/modules/mbedtls/dtls_server_mbedtls.h +++ b/modules/mbedtls/dtls_server_mbedtls.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef MBED_DTLS_SERVER_H -#define MBED_DTLS_SERVER_H +#ifndef DTLS_SERVER_MBEDTLS_H +#define DTLS_SERVER_MBEDTLS_H #include "core/io/dtls_server.h" #include "ssl_context_mbedtls.h" @@ -54,4 +54,4 @@ public: ~DTLSServerMbedTLS(); }; -#endif // MBED_DTLS_SERVER_H +#endif // DTLS_SERVER_MBEDTLS_H diff --git a/modules/mbedtls/ssl_context_mbedtls.h b/modules/mbedtls/ssl_context_mbedtls.h index dd49792abd..5883388311 100644 --- a/modules/mbedtls/ssl_context_mbedtls.h +++ b/modules/mbedtls/ssl_context_mbedtls.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SSL_CONTEXT_MBED_TLS_H -#define SSL_CONTEXT_MBED_TLS_H +#ifndef SSL_CONTEXT_MBEDTLS_H +#define SSL_CONTEXT_MBEDTLS_H #include "crypto_mbedtls.h" @@ -90,4 +90,4 @@ public: ~SSLContextMbedTLS(); }; -#endif // SSL_CONTEXT_MBED_TLS_H +#endif // SSL_CONTEXT_MBEDTLS_H diff --git a/modules/mbedtls/stream_peer_mbedtls.h b/modules/mbedtls/stream_peer_mbedtls.h index 7660410e04..68b07feea9 100644 --- a/modules/mbedtls/stream_peer_mbedtls.h +++ b/modules/mbedtls/stream_peer_mbedtls.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef STREAM_PEER_OPEN_SSL_H -#define STREAM_PEER_OPEN_SSL_H +#ifndef STREAM_PEER_MBEDTLS_H +#define STREAM_PEER_MBEDTLS_H #include "core/io/stream_peer_ssl.h" #include "ssl_context_mbedtls.h" @@ -76,4 +76,4 @@ public: ~StreamPeerMbedTLS(); }; -#endif // STREAM_PEER_SSL_H +#endif // STREAM_PEER_MBEDTLS_H diff --git a/modules/meshoptimizer/register_types.h b/modules/meshoptimizer/register_types.h index 99c71efceb..3a84aab7bc 100644 --- a/modules/meshoptimizer/register_types.h +++ b/modules/meshoptimizer/register_types.h @@ -36,4 +36,4 @@ void initialize_meshoptimizer_module(ModuleInitializationLevel p_level); void uninitialize_meshoptimizer_module(ModuleInitializationLevel p_level); -#endif // PVR_REGISTER_TYPES_H +#endif // MESHOPTIMIZER_REGISTER_TYPES_H diff --git a/modules/minimp3/audio_stream_mp3.cpp b/modules/minimp3/audio_stream_mp3.cpp index c37bea519f..98bcdea8f4 100644 --- a/modules/minimp3/audio_stream_mp3.cpp +++ b/modules/minimp3/audio_stream_mp3.cpp @@ -46,6 +46,12 @@ int AudioStreamPlaybackMP3::_mix_internal(AudioFrame *p_buffer, int p_frames) { int frames_mixed_this_step = p_frames; + int beat_length_frames = -1; + bool beat_loop = mp3_stream->has_loop() && mp3_stream->get_bpm() > 0 && mp3_stream->get_beat_count() > 0; + if (beat_loop) { + beat_length_frames = mp3_stream->get_beat_count() * mp3_stream->sample_rate * 60 / mp3_stream->get_bpm(); + } + while (todo && active) { mp3dec_frame_info_t frame_info; mp3d_sample_t *buf_frame = nullptr; @@ -54,8 +60,25 @@ int AudioStreamPlaybackMP3::_mix_internal(AudioFrame *p_buffer, int p_frames) { if (samples_mixed) { p_buffer[p_frames - todo] = AudioFrame(buf_frame[0], buf_frame[samples_mixed - 1]); + if (loop_fade_remaining < FADE_SIZE) { + p_buffer[p_frames - todo] += loop_fade[loop_fade_remaining] * (float(FADE_SIZE - loop_fade_remaining) / float(FADE_SIZE)); + loop_fade_remaining++; + } --todo; ++frames_mixed; + + if (beat_loop && (int)frames_mixed >= beat_length_frames) { + for (int i = 0; i < FADE_SIZE; i++) { + samples_mixed = mp3dec_ex_read_frame(mp3d, &buf_frame, &frame_info, mp3_stream->channels); + loop_fade[i] = AudioFrame(buf_frame[0], buf_frame[samples_mixed - 1]); + if (!samples_mixed) { + break; + } + } + loop_fade_remaining = 0; + seek(mp3_stream->loop_offset); + loops++; + } } else { @@ -117,6 +140,10 @@ void AudioStreamPlaybackMP3::seek(float p_time) { mp3dec_ex_seek(mp3d, (uint64_t)frames_mixed * mp3_stream->channels); } +void AudioStreamPlaybackMP3::tag_used_streams() { + mp3_stream->tag_used(get_playback_position()); +} + AudioStreamPlaybackMP3::~AudioStreamPlaybackMP3() { if (mp3d) { mp3dec_ex_close(mp3d); @@ -124,7 +151,7 @@ AudioStreamPlaybackMP3::~AudioStreamPlaybackMP3() { } } -Ref<AudioStreamPlayback> AudioStreamMP3::instance_playback() { +Ref<AudioStreamPlayback> AudioStreamMP3::instantiate_playback() { Ref<AudioStreamPlaybackMP3> mp3s; ERR_FAIL_COND_V_MSG(data.is_empty(), mp3s, @@ -206,6 +233,36 @@ bool AudioStreamMP3::is_monophonic() const { return false; } +void AudioStreamMP3::set_bpm(double p_bpm) { + ERR_FAIL_COND(p_bpm < 0); + bpm = p_bpm; + emit_changed(); +} + +double AudioStreamMP3::get_bpm() const { + return bpm; +} + +void AudioStreamMP3::set_beat_count(int p_beat_count) { + ERR_FAIL_COND(p_beat_count < 0); + beat_count = p_beat_count; + emit_changed(); +} + +int AudioStreamMP3::get_beat_count() const { + return beat_count; +} + +void AudioStreamMP3::set_bar_beats(int p_bar_beats) { + ERR_FAIL_COND(p_bar_beats < 0); + bar_beats = p_bar_beats; + emit_changed(); +} + +int AudioStreamMP3::get_bar_beats() const { + return bar_beats; +} + void AudioStreamMP3::_bind_methods() { ClassDB::bind_method(D_METHOD("set_data", "data"), &AudioStreamMP3::set_data); ClassDB::bind_method(D_METHOD("get_data"), &AudioStreamMP3::get_data); @@ -216,7 +273,19 @@ void AudioStreamMP3::_bind_methods() { ClassDB::bind_method(D_METHOD("set_loop_offset", "seconds"), &AudioStreamMP3::set_loop_offset); ClassDB::bind_method(D_METHOD("get_loop_offset"), &AudioStreamMP3::get_loop_offset); + ClassDB::bind_method(D_METHOD("set_bpm", "bpm"), &AudioStreamMP3::set_bpm); + ClassDB::bind_method(D_METHOD("get_bpm"), &AudioStreamMP3::get_bpm); + + ClassDB::bind_method(D_METHOD("set_beat_count", "count"), &AudioStreamMP3::set_beat_count); + ClassDB::bind_method(D_METHOD("get_beat_count"), &AudioStreamMP3::get_beat_count); + + ClassDB::bind_method(D_METHOD("set_bar_beats", "count"), &AudioStreamMP3::set_bar_beats); + ClassDB::bind_method(D_METHOD("get_bar_beats"), &AudioStreamMP3::get_bar_beats); + ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_data", "get_data"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bpm", PROPERTY_HINT_RANGE, "0,400,0.01,or_greater"), "set_bpm", "get_bpm"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "beat_count", PROPERTY_HINT_RANGE, "0,512,1,or_greater"), "set_beat_count", "get_beat_count"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "bar_beats", PROPERTY_HINT_RANGE, "2,32,1,or_greater"), "set_bar_beats", "get_bar_beats"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "loop_offset"), "set_loop_offset", "get_loop_offset"); } diff --git a/modules/minimp3/audio_stream_mp3.h b/modules/minimp3/audio_stream_mp3.h index c1a60ddccb..428ac1240e 100644 --- a/modules/minimp3/audio_stream_mp3.h +++ b/modules/minimp3/audio_stream_mp3.h @@ -41,6 +41,12 @@ class AudioStreamMP3; class AudioStreamPlaybackMP3 : public AudioStreamPlaybackResampled { GDCLASS(AudioStreamPlaybackMP3, AudioStreamPlaybackResampled); + enum { + FADE_SIZE = 256 + }; + AudioFrame loop_fade[FADE_SIZE]; + int loop_fade_remaining = FADE_SIZE; + mp3dec_ex_t *mp3d = nullptr; uint32_t frames_mixed = 0; bool active = false; @@ -64,6 +70,8 @@ public: virtual float get_playback_position() const override; virtual void seek(float p_time) override; + virtual void tag_used_streams() override; + AudioStreamPlaybackMP3() {} ~AudioStreamPlaybackMP3(); }; @@ -85,17 +93,30 @@ class AudioStreamMP3 : public AudioStream { float loop_offset = 0.0; void clear_data(); + double bpm = 0; + int beat_count = 0; + int bar_beats = 4; + protected: static void _bind_methods(); public: void set_loop(bool p_enable); - bool has_loop() const; + virtual bool has_loop() const override; void set_loop_offset(float p_seconds); float get_loop_offset() const; - virtual Ref<AudioStreamPlayback> instance_playback() override; + void set_bpm(double p_bpm); + virtual double get_bpm() const override; + + void set_beat_count(int p_beat_count); + virtual int get_beat_count() const override; + + void set_bar_beats(int p_bar_beats); + virtual int get_bar_beats() const override; + + virtual Ref<AudioStreamPlayback> instantiate_playback() override; virtual String get_stream_name() const override; void set_data(const Vector<uint8_t> &p_data); diff --git a/modules/minimp3/doc_classes/AudioStreamMP3.xml b/modules/minimp3/doc_classes/AudioStreamMP3.xml index f5f7d3ef17..8f03681c06 100644 --- a/modules/minimp3/doc_classes/AudioStreamMP3.xml +++ b/modules/minimp3/doc_classes/AudioStreamMP3.xml @@ -4,13 +4,42 @@ MP3 audio stream driver. </brief_description> <description> - MP3 audio stream driver. + MP3 audio stream driver. See [member data] if you want to load an MP3 file at run-time. </description> <tutorials> </tutorials> <members> + <member name="bar_beats" type="int" setter="set_bar_beats" getter="get_bar_beats" default="4"> + </member> + <member name="beat_count" type="int" setter="set_beat_count" getter="get_beat_count" default="0"> + </member> + <member name="bpm" type="float" setter="set_bpm" getter="get_bpm" default="0.0"> + </member> <member name="data" type="PackedByteArray" setter="set_data" getter="get_data" default="PackedByteArray()"> Contains the audio data in bytes. + You can load a file without having to import it beforehand using the code snippet below. Keep in mind that this snippet loads the whole file into memory and may not be ideal for huge files (hundreds of megabytes or more). + [codeblocks] + [gdscript] + func load_mp3(path): + var file = File.new() + file.open(path, File.READ) + var sound = AudioStreamMP3.new() + sound.data = file.get_buffer(file.get_length()) + file.close() + return sound + [/gdscript] + [csharp] + public AudioStreamMP3 LoadMP3(string path) + { + var file = new File(); + file.Open(path, File.READ); + var sound = new AudioStreamMP3(); + sound.Data = file.GetBuffer(file.GetLength()); + file.Close(); + return sound; + } + [/csharp] + [/codeblocks] </member> <member name="loop" type="bool" setter="set_loop" getter="has_loop" default="false"> If [code]true[/code], the stream will automatically loop when it reaches the end. diff --git a/modules/minimp3/resource_importer_mp3.cpp b/modules/minimp3/resource_importer_mp3.cpp index e03940f963..8526aeef38 100644 --- a/modules/minimp3/resource_importer_mp3.cpp +++ b/modules/minimp3/resource_importer_mp3.cpp @@ -34,6 +34,10 @@ #include "core/io/resource_saver.h" #include "scene/resources/texture.h" +#ifdef TOOLS_ENABLED +#include "editor/import/audio_stream_import_settings.h" +#endif + String ResourceImporterMP3::get_importer_name() const { return "mp3"; } @@ -69,14 +73,26 @@ String ResourceImporterMP3::get_preset_name(int p_idx) const { void ResourceImporterMP3::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "loop"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "loop_offset"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "bpm", PROPERTY_HINT_RANGE, "0,400,0.01,or_greater"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "beat_count", PROPERTY_HINT_RANGE, "0,512,or_greater"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "bar_beats", PROPERTY_HINT_RANGE, "2,32,or_greater"), 4)); } -Error ResourceImporterMP3::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { - bool loop = p_options["loop"]; - float loop_offset = p_options["loop_offset"]; +#ifdef TOOLS_ENABLED +bool ResourceImporterMP3::has_advanced_options() const { + return true; +} +void ResourceImporterMP3::show_advanced_options(const String &p_path) { + Ref<AudioStreamMP3> mp3_stream = import_mp3(p_path); + if (mp3_stream.is_valid()) { + AudioStreamImportSettings::get_singleton()->edit(p_path, "mp3", mp3_stream); + } +} +#endif - Ref<FileAccess> f = FileAccess::open(p_source_file, FileAccess::READ); - ERR_FAIL_COND_V(f.is_null(), ERR_CANT_OPEN); +Ref<AudioStreamMP3> ResourceImporterMP3::import_mp3(const String &p_path) { + Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); + ERR_FAIL_COND_V(f.is_null(), Ref<AudioStreamMP3>()); uint64_t len = f->get_length(); @@ -90,9 +106,27 @@ Error ResourceImporterMP3::import(const String &p_source_file, const String &p_s mp3_stream.instantiate(); mp3_stream->set_data(data); - ERR_FAIL_COND_V(!mp3_stream->get_data().size(), ERR_FILE_CORRUPT); + ERR_FAIL_COND_V(!mp3_stream->get_data().size(), Ref<AudioStreamMP3>()); + + return mp3_stream; +} + +Error ResourceImporterMP3::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { + bool loop = p_options["loop"]; + float loop_offset = p_options["loop_offset"]; + double bpm = p_options["bpm"]; + float beat_count = p_options["beat_count"]; + float bar_beats = p_options["bar_beats"]; + + Ref<AudioStreamMP3> mp3_stream = import_mp3(p_source_file); + if (mp3_stream.is_null()) { + return ERR_CANT_OPEN; + } mp3_stream->set_loop(loop); mp3_stream->set_loop_offset(loop_offset); + mp3_stream->set_bpm(bpm); + mp3_stream->set_beat_count(beat_count); + mp3_stream->set_bar_beats(bar_beats); return ResourceSaver::save(p_save_path + ".mp3str", mp3_stream); } diff --git a/modules/minimp3/resource_importer_mp3.h b/modules/minimp3/resource_importer_mp3.h index 678a3773bb..38729d68f8 100644 --- a/modules/minimp3/resource_importer_mp3.h +++ b/modules/minimp3/resource_importer_mp3.h @@ -50,6 +50,12 @@ public: virtual void get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset = 0) const override; virtual bool get_option_visibility(const String &p_path, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; +#ifdef TOOLS_ENABLED + virtual bool has_advanced_options() const override; + virtual void show_advanced_options(const String &p_path) override; +#endif + static Ref<AudioStreamMP3> import_mp3(const String &p_path); + virtual Error import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files = nullptr, Variant *r_metadata = nullptr) override; ResourceImporterMP3(); diff --git a/modules/mobile_vr/mobile_vr_interface.cpp b/modules/mobile_vr/mobile_vr_interface.cpp index 5876b6cbf3..b14f5f469c 100644 --- a/modules/mobile_vr/mobile_vr_interface.cpp +++ b/modules/mobile_vr/mobile_vr_interface.cpp @@ -45,7 +45,7 @@ uint32_t MobileVRInterface::get_capabilities() const { Vector3 MobileVRInterface::scale_magneto(const Vector3 &p_magnetometer) { // Our magnetometer doesn't give us nice clean data. - // Well it may on Mac OS X because we're getting a calibrated value in the current implementation but Android we're getting raw data. + // Well it may on macOS because we're getting a calibrated value in the current implementation but Android we're getting raw data. // This is a fairly simple adjustment we can do to correct for the magnetometer data being elliptical Vector3 mag_raw = p_magnetometer; @@ -452,10 +452,10 @@ Transform3D MobileVRInterface::get_transform_for_view(uint32_t p_view, const Tra return transform_for_eye; }; -CameraMatrix MobileVRInterface::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) { +Projection MobileVRInterface::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) { _THREAD_SAFE_METHOD_ - CameraMatrix eye; + Projection eye; aspect = p_aspect; eye.set_for_hmd(p_view + 1, p_aspect, intraocular_dist, display_width, display_to_lens, oversample, p_z_near, p_z_far); diff --git a/modules/mobile_vr/mobile_vr_interface.h b/modules/mobile_vr/mobile_vr_interface.h index 8ecca3a2ae..b934a09dd3 100644 --- a/modules/mobile_vr/mobile_vr_interface.h +++ b/modules/mobile_vr/mobile_vr_interface.h @@ -150,7 +150,7 @@ public: virtual uint32_t get_view_count() override; virtual Transform3D get_camera_transform() override; virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override; - virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override; + virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override; virtual Vector<BlitToScreen> post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) override; virtual void process() override; diff --git a/modules/mono/SCsub b/modules/mono/SCsub index 3bafa351a9..d10ebc7b47 100644 --- a/modules/mono/SCsub +++ b/modules/mono/SCsub @@ -55,7 +55,7 @@ env_mono.add_source_files(env.modules_sources, "utils/*.cpp") env_mono.add_source_files(env.modules_sources, "mono_gd/support/*.cpp") -if env["platform"] in ["osx", "iphone"]: +if env["platform"] in ["macos", "ios"]: env_mono.add_source_files(env.modules_sources, "mono_gd/support/*.mm") env_mono.add_source_files(env.modules_sources, "mono_gd/support/*.m") elif env["platform"] == "android": diff --git a/modules/mono/build_scripts/make_android_mono_config.py b/modules/mono/build_scripts/make_android_mono_config.py index 1920ef1c1a..3459244bc2 100644 --- a/modules/mono/build_scripts/make_android_mono_config.py +++ b/modules/mono/build_scripts/make_android_mono_config.py @@ -43,7 +43,7 @@ String get_godot_android_mono_config() { Compression::decompress(w, config_uncompressed_size, config_compressed_data, config_compressed_size, Compression::MODE_DEFLATE); String s; - if (s.parse_utf8((const char *)w, data.size())) { + if (s.parse_utf8((const char *)w, data.size()) != OK) { ERR_FAIL_V(String()); } return s; diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py index 8e441e7e07..e69904c54b 100644 --- a/modules/mono/build_scripts/mono_configure.py +++ b/modules/mono/build_scripts/mono_configure.py @@ -63,15 +63,15 @@ def copy_file(src_dir, dst_dir, src_name, dst_name=""): def is_desktop(platform): - return platform in ["windows", "osx", "linuxbsd", "server", "uwp", "haiku"] + return platform in ["windows", "macos", "linuxbsd", "server", "uwp", "haiku"] def is_unix_like(platform): - return platform in ["osx", "linuxbsd", "server", "android", "haiku", "iphone"] + return platform in ["macos", "linuxbsd", "server", "android", "haiku", "ios"] def module_supports_tools_on(platform): - return platform not in ["android", "javascript", "iphone"] + return platform not in ["android", "javascript", "ios"] def find_wasm_src_dir(mono_root): @@ -89,7 +89,7 @@ def configure(env, env_mono): bits = env["bits"] is_android = env["platform"] == "android" is_javascript = env["platform"] == "javascript" - is_ios = env["platform"] == "iphone" + is_ios = env["platform"] == "ios" is_ios_sim = is_ios and env["arch"] in ["x86", "x86_64"] tools_enabled = env["tools"] @@ -206,7 +206,7 @@ def configure(env, env_mono): copy_file(mono_bin_path, "#bin", mono_dll_file) else: - is_apple = env["platform"] in ["osx", "iphone"] + is_apple = env["platform"] in ["macos", "ios"] is_macos = is_apple and not is_ios sharedlib_ext = ".dylib" if is_apple else ".so" @@ -221,7 +221,7 @@ def configure(env, env_mono): ) if not mono_root and is_macos: - # Try with some known directories under OSX + # Try with some known directories under macOS hint_dirs = ["/Library/Frameworks/Mono.framework/Versions/Current", "/usr/local/var/homebrew/linked/mono"] for hint_dir in hint_dirs: if os.path.isdir(hint_dir): @@ -270,7 +270,7 @@ def configure(env, env_mono): def copy_mono_lib(libname_wo_ext): copy_file( - mono_lib_path, "#bin", libname_wo_ext + ".a", "%s.iphone.%s.a" % (libname_wo_ext, arch) + mono_lib_path, "#bin", libname_wo_ext + ".a", "%s.ios.%s.a" % (libname_wo_ext, arch) ) # Copy Mono libraries to the output folder. These are meant to be bundled with @@ -539,7 +539,7 @@ def copy_mono_shared_libs(env, mono_root, target_mono_root_dir): os.makedirs(target_mono_lib_dir) lib_file_names = [] - if platform == "osx": + if platform == "macos": lib_file_names = [ lib_name + ".dylib" for lib_name in ["libmono-btls-shared", "libmono-native-compat", "libMonoPosixHelper"] diff --git a/modules/mono/config.py b/modules/mono/config.py index df02d9a309..3e6584590c 100644 --- a/modules/mono/config.py +++ b/modules/mono/config.py @@ -1,4 +1,4 @@ -supported_platforms = ["windows", "osx", "linuxbsd", "server", "android", "haiku", "javascript", "iphone"] +supported_platforms = ["windows", "macos", "linuxbsd", "server", "android", "haiku", "javascript", "ios"] def can_build(env, platform): @@ -15,7 +15,7 @@ def configure(env): from SCons.Script import BoolVariable, PathVariable, Variables, Help - default_mono_static = platform in ["iphone", "javascript"] + default_mono_static = platform in ["ios", "javascript"] default_mono_bundles_zlib = platform in ["javascript"] envvars = Variables() diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 622838b308..1e4d82ca30 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -481,11 +481,14 @@ static String variant_type_to_managed_name(const String &p_var_type_name) { Variant::VECTOR3, Variant::VECTOR3I, Variant::TRANSFORM2D, + Variant::VECTOR4, + Variant::VECTOR4I, Variant::PLANE, Variant::QUATERNION, Variant::AABB, Variant::BASIS, Variant::TRANSFORM3D, + Variant::PROJECTION, Variant::COLOR, Variant::STRING_NAME, Variant::NODE_PATH, @@ -2866,6 +2869,12 @@ int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, Manage r_hint = PROPERTY_HINT_RESOURCE_TYPE; r_hint_string = String(NATIVE_GDMONOCLASS_NAME(field_native_class)); + } else if (p_variant_type == Variant::OBJECT && CACHED_CLASS(Node)->is_assignable_from(p_type.type_class)) { + GDMonoClass *field_native_class = GDMonoUtils::get_class_native_base(p_type.type_class); + CRASH_COND(field_native_class == nullptr); + + r_hint = PROPERTY_HINT_NODE_TYPE; + r_hint_string = String(NATIVE_GDMONOCLASS_NAME(field_native_class)); } else if (p_allow_generics && p_variant_type == Variant::ARRAY) { // Nested arrays are not supported in the inspector @@ -3063,16 +3072,11 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) { Vector<GDMonoMethod *> methods = top->get_all_methods(); for (int i = 0; i < methods.size(); i++) { if (!methods[i]->is_static()) { - Multiplayer::RPCMode mode = p_script->_member_get_rpc_mode(methods[i]); - if (Multiplayer::RPC_MODE_DISABLED != mode) { - Multiplayer::RPCConfig nd; - nd.name = methods[i]->get_name(); - nd.rpc_mode = mode; - // TODO Transfer mode, channel - nd.transfer_mode = Multiplayer::TRANSFER_MODE_RELIABLE; - nd.channel = 0; - if (-1 == p_script->rpc_functions.find(nd)) { - p_script->rpc_functions.push_back(nd); + Multiplayer::RPCConfig rpc_config = p_script->_member_get_rpc_config(methods[i]); + if (rpc_config.rpc_mode != Multiplayer::RPC_MODE_DISABLED) { + // RPC annotations can only be used once per method + if (p_script->rpc_functions.find(rpc_config) == -1) { + p_script->rpc_functions.push_back(rpc_config); } } } @@ -3507,15 +3511,19 @@ int CSharpScript::get_member_line(const StringName &p_member) const { return -1; } -Multiplayer::RPCMode CSharpScript::_member_get_rpc_mode(IMonoClassMember *p_member) const { - if (p_member->has_attribute(CACHED_CLASS(AnyPeerAttribute))) { - return Multiplayer::RPC_MODE_ANY_PEER; - } - if (p_member->has_attribute(CACHED_CLASS(AuthorityAttribute))) { - return Multiplayer::RPC_MODE_AUTHORITY; +Multiplayer::RPCConfig CSharpScript::_member_get_rpc_config(IMonoClassMember *p_member) const { + Multiplayer::RPCConfig rpc_config; + + MonoObject *rpc_attribute = p_member->get_attribute(CACHED_CLASS(RPCAttribute)); + if (rpc_attribute != nullptr) { + rpc_config.name = p_member->get_name(); + rpc_config.rpc_mode = (Multiplayer::RPCMode)CACHED_PROPERTY(RPCAttribute, Mode)->get_int_value(rpc_attribute); + rpc_config.call_local = CACHED_PROPERTY(RPCAttribute, CallLocal)->get_bool_value(rpc_attribute); + rpc_config.transfer_mode = (Multiplayer::TransferMode)CACHED_PROPERTY(RPCAttribute, TransferMode)->get_int_value(rpc_attribute); + rpc_config.channel = CACHED_PROPERTY(RPCAttribute, TransferChannel)->get_int_value(rpc_attribute); } - return Multiplayer::RPC_MODE_DISABLED; + return rpc_config; } const Vector<Multiplayer::RPCConfig> CSharpScript::get_rpc_methods() const { diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index 69bd8703aa..b17473470f 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -179,7 +179,7 @@ private: static void update_script_class_info(Ref<CSharpScript> p_script); static void initialize_for_managed_type(Ref<CSharpScript> p_script, GDMonoClass *p_class, GDMonoClass *p_native); - Multiplayer::RPCMode _member_get_rpc_mode(IMonoClassMember *p_member) const; + Multiplayer::RPCConfig _member_get_rpc_config(IMonoClassMember *p_member) const; protected: static void _bind_methods(); @@ -502,6 +502,7 @@ public: /* TODO? */ void get_public_functions(List<MethodInfo> *p_functions) const override {} /* TODO? */ void get_public_constants(List<Pair<String, Variant>> *p_constants) const override {} + /* TODO? */ void get_public_annotations(List<MethodInfo> *p_annotations) const override {} void reload_all_scripts() override; void reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) override; diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props index 0128f5c706..5a499742e9 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Sdk.props @@ -57,7 +57,7 @@ <PropertyGroup Condition=" '$(GodotTargetPlatform)' == '' "> <GodotTargetPlatform Condition=" '$([MSBuild]::IsOsPlatform(Linux))' ">linuxbsd</GodotTargetPlatform> <GodotTargetPlatform Condition=" '$([MSBuild]::IsOsPlatform(FreeBSD))' ">linuxbsd</GodotTargetPlatform> - <GodotTargetPlatform Condition=" '$([MSBuild]::IsOsPlatform(OSX))' ">osx</GodotTargetPlatform> + <GodotTargetPlatform Condition=" '$([MSBuild]::IsOsPlatform(OSX))' ">macos</GodotTargetPlatform> <GodotTargetPlatform Condition=" '$([MSBuild]::IsOsPlatform(Windows))' ">windows</GodotTargetPlatform> </PropertyGroup> @@ -76,12 +76,12 @@ --> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'windows' ">GODOT_WINDOWS;GODOT_PC</GodotPlatformConstants> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'linuxbsd' ">GODOT_LINUXBSD;GODOT_PC</GodotPlatformConstants> - <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'osx' ">GODOT_OSX;GODOT_MACOS;GODOT_PC</GodotPlatformConstants> + <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'macos' ">GODOT_OSX;GODOT_MACOS;GODOT_PC</GodotPlatformConstants> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'server' ">GODOT_SERVER;GODOT_PC</GodotPlatformConstants> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'uwp' ">GODOT_UWP;GODOT_PC</GodotPlatformConstants> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'haiku' ">GODOT_HAIKU;GODOT_PC</GodotPlatformConstants> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'android' ">GODOT_ANDROID;GODOT_MOBILE</GodotPlatformConstants> - <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'iphone' ">GODOT_IPHONE;GODOT_IOS;GODOT_MOBILE</GodotPlatformConstants> + <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'ios' ">GODOT_IPHONE;GODOT_IOS;GODOT_MOBILE</GodotPlatformConstants> <GodotPlatformConstants Condition=" '$(GodotTargetPlatform)' == 'javascript' ">GODOT_JAVASCRIPT;GODOT_HTML5;GODOT_WASM;GODOT_WEB</GodotPlatformConstants> <GodotDefineConstants>$(GodotDefineConstants);$(GodotPlatformConstants)</GodotDefineConstants> diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs b/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs index 16dd1c8c6b..63b97e981e 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/NuGetUtils.cs @@ -99,7 +99,7 @@ namespace GodotTools.Build if (Utils.OS.IsWindows) { // %APPDATA% for both - return new[] {Path.Combine(applicationData, "NuGet", "NuGet.Config")}; + return new[] { Path.Combine(applicationData, "NuGet", "NuGet.Config") }; } var paths = new string[2]; @@ -156,6 +156,7 @@ namespace GodotTools.Build </packageSources> </configuration> "; + System.IO.Directory.CreateDirectory(Path.GetDirectoryName(nuGetConfigPath)); System.IO.File.WriteAllText(nuGetConfigPath, defaultConfig, Encoding.UTF8); // UTF-8 with BOM } diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs index e2f4d2f5fd..e9718cc82c 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Export/AotBuilder.cs @@ -336,10 +336,10 @@ MONO_AOT_MODE_LAST = 1000, // Add the required Mono libraries to the Xcode project - string MonoLibFile(string libFileName) => libFileName + ".iphone.fat.a"; + string MonoLibFile(string libFileName) => libFileName + ".ios.fat.a"; string MonoLibFromTemplate(string libFileName) => - Path.Combine(Internal.FullTemplatesDir, "iphone-mono-libs", MonoLibFile(libFileName)); + Path.Combine(Internal.FullExportTemplatesDir, "ios-mono-libs", MonoLibFile(libFileName)); exporter.AddIosProjectStaticLib(MonoLibFromTemplate("libmonosgen-2.0")); diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs index 3e46a89b7c..cca18a2a1f 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs @@ -337,7 +337,7 @@ namespace GodotTools.Export string TemplateDirName() => $"data.mono.{platform}.{bits}.{target}"; - string templateDirPath = Path.Combine(Internal.FullTemplatesDir, TemplateDirName()); + string templateDirPath = Path.Combine(Internal.FullExportTemplatesDir, TemplateDirName()); bool validTemplatePathFound = true; if (!Directory.Exists(templateDirPath)) @@ -347,7 +347,7 @@ namespace GodotTools.Export if (isDebug) { target = "debug"; // Support both 'release_debug' and 'debug' for the template data directory name - templateDirPath = Path.Combine(Internal.FullTemplatesDir, TemplateDirName()); + templateDirPath = Path.Combine(Internal.FullExportTemplatesDir, TemplateDirName()); validTemplatePathFound = true; if (!Directory.Exists(templateDirPath)) @@ -380,7 +380,7 @@ namespace GodotTools.Export private static bool PlatformHasTemplateDir(string platform) { - // OSX export templates are contained in a zip, so we place our custom template inside it and let Godot do the rest. + // macOS export templates are contained in a zip, so we place our custom template inside it and let Godot do the rest. return !new[] { OS.Platforms.MacOS, OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5 }.Contains(platform); } @@ -398,13 +398,13 @@ namespace GodotTools.Export private static string GetBclProfileDir(string profile) { - string templatesDir = Internal.FullTemplatesDir; + string templatesDir = Internal.FullExportTemplatesDir; return Path.Combine(templatesDir, "bcl", profile); } private static string DeterminePlatformBclDir(string platform) { - string templatesDir = Internal.FullTemplatesDir; + string templatesDir = Internal.FullExportTemplatesDir; string platformBclDir = Path.Combine(templatesDir, "bcl", platform); if (!File.Exists(Path.Combine(platformBclDir, "mscorlib.dll"))) diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs index 69960bdbeb..b39c3d1c0d 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs +++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs @@ -263,16 +263,16 @@ namespace GodotTools var args = new List<string>(); - bool osxAppBundleInstalled = false; + bool macOSAppBundleInstalled = false; if (OS.IsMacOS) { // The package path is '/Applications/Visual Studio Code.app' const string vscodeBundleId = "com.microsoft.VSCode"; - osxAppBundleInstalled = Internal.IsOsxAppBundleInstalled(vscodeBundleId); + macOSAppBundleInstalled = Internal.IsMacOSAppBundleInstalled(vscodeBundleId); - if (osxAppBundleInstalled) + if (macOSAppBundleInstalled) { args.Add("-b"); args.Add(vscodeBundleId); @@ -307,13 +307,13 @@ namespace GodotTools if (OS.IsMacOS) { - if (!osxAppBundleInstalled && string.IsNullOrEmpty(_vsCodePath)) + if (!macOSAppBundleInstalled && string.IsNullOrEmpty(_vsCodePath)) { GD.PushError("Cannot find code editor: VSCode"); return Error.FileNotFound; } - command = osxAppBundleInstalled ? "/usr/bin/open" : _vsCodePath; + command = macOSAppBundleInstalled ? "/usr/bin/open" : _vsCodePath; } else { diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs index 3f1d5ac3ca..7a0983a8cb 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Ides/MonoDevelop/Instance.cs @@ -30,7 +30,7 @@ namespace GodotTools.Ides.MonoDevelop { string bundleId = BundleIds[_editorId]; - if (Internal.IsOsxAppBundleInstalled(bundleId)) + if (Internal.IsMacOSAppBundleInstalled(bundleId)) { command = "open"; diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs index 77370090ec..12c90178c9 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs @@ -12,12 +12,12 @@ namespace GodotTools.Internals public static string UpdateApiAssembliesFromPrebuilt(string config) => internal_UpdateApiAssembliesFromPrebuilt(config); - public static string FullTemplatesDir => - internal_FullTemplatesDir(); + public static string FullExportTemplatesDir => + internal_FullExportTemplatesDir(); public static string SimplifyGodotPath(this string path) => internal_SimplifyGodotPath(path); - public static bool IsOsxAppBundleInstalled(string bundleId) => internal_IsOsxAppBundleInstalled(bundleId); + public static bool IsMacOSAppBundleInstalled(string bundleId) => internal_IsMacOSAppBundleInstalled(bundleId); public static bool GodotIs32Bits() => internal_GodotIs32Bits(); @@ -57,13 +57,13 @@ namespace GodotTools.Internals private static extern string internal_UpdateApiAssembliesFromPrebuilt(string config); [MethodImpl(MethodImplOptions.InternalCall)] - private static extern string internal_FullTemplatesDir(); + private static extern string internal_FullExportTemplatesDir(); [MethodImpl(MethodImplOptions.InternalCall)] private static extern string internal_SimplifyGodotPath(this string path); [MethodImpl(MethodImplOptions.InternalCall)] - private static extern bool internal_IsOsxAppBundleInstalled(string bundleId); + private static extern bool internal_IsMacOSAppBundleInstalled(string bundleId); [MethodImpl(MethodImplOptions.InternalCall)] private static extern bool internal_GodotIs32Bits(); diff --git a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs index 2db549c623..5cef6e5c3c 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Utils/OS.cs @@ -37,13 +37,13 @@ namespace GodotTools.Utils public static class Platforms { public const string Windows = "windows"; - public const string MacOS = "osx"; + public const string MacOS = "macos"; public const string LinuxBSD = "linuxbsd"; public const string Server = "server"; public const string UWP = "uwp"; public const string Haiku = "haiku"; public const string Android = "android"; - public const string iOS = "iphone"; + public const string iOS = "ios"; public const string HTML5 = "javascript"; } diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 9d3d481068..2e628cb576 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -917,6 +917,8 @@ void BindingsGenerator::_generate_array_extensions(StringBuilder &p_output) { ARRAY_ALL(Vector2i); ARRAY_ALL(Vector3); ARRAY_ALL(Vector3i); + ARRAY_ALL(Vector4); + ARRAY_ALL(Vector4i); #undef ARRAY_ALL #undef ARRAY_IS_EMPTY @@ -990,6 +992,10 @@ void BindingsGenerator::_generate_global_constants(StringBuilder &p_output) { p_output.append("\n" INDENT1 OPEN_BLOCK); } + if (ienum.is_flags) { + p_output.append("\n" INDENT1 "[System.Flags]"); + } + p_output.append("\n" INDENT1 "public enum "); p_output.append(enum_proxy_name); p_output.append(" : long"); @@ -1434,6 +1440,10 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str for (const EnumInterface &ienum : itype.enums) { ERR_FAIL_COND_V(ienum.constants.is_empty(), ERR_BUG); + if (ienum.is_flags) { + output.append(MEMBER_BEGIN "[System.Flags]"); + } + output.append(MEMBER_BEGIN "public enum "); output.append(ienum.cname.operator String()); output.append(" : long"); @@ -2865,7 +2875,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { " We only expected Object.free, but found '" + itype.name + "." + imethod.name + "'."); } - } else if (return_info.type == Variant::INT && return_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { + } else if (return_info.type == Variant::INT && return_info.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) { imethod.return_type.cname = return_info.class_name; imethod.return_type.is_enum = true; } else if (return_info.class_name != StringName()) { @@ -2903,7 +2913,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { ArgumentInterface iarg; iarg.name = orig_arg_name; - if (arginfo.type == Variant::INT && arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { + if (arginfo.type == Variant::INT && arginfo.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) { iarg.type.cname = arginfo.class_name; iarg.type.is_enum = true; } else if (arginfo.class_name != StringName()) { @@ -3011,7 +3021,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() { ArgumentInterface iarg; iarg.name = orig_arg_name; - if (arginfo.type == Variant::INT && arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { + if (arginfo.type == Variant::INT && arginfo.usage & (PROPERTY_USAGE_CLASS_IS_ENUM | PROPERTY_USAGE_CLASS_IS_BITFIELD)) { iarg.type.cname = arginfo.class_name; iarg.type.is_enum = true; } else if (arginfo.class_name != StringName()) { @@ -3075,9 +3085,9 @@ bool BindingsGenerator::_populate_object_type_interfaces() { List<String> constants; ClassDB::get_integer_constant_list(type_cname, &constants, true); - const HashMap<StringName, List<StringName>> &enum_map = class_info->enum_map; + const HashMap<StringName, ClassDB::ClassInfo::EnumInfo> &enum_map = class_info->enum_map; - for (const KeyValue<StringName, List<StringName>> &E : enum_map) { + for (const KeyValue<StringName, ClassDB::ClassInfo::EnumInfo> &E : enum_map) { StringName enum_proxy_cname = E.key; String enum_proxy_name = enum_proxy_cname.operator String(); if (itype.find_property_by_proxy_name(enum_proxy_cname)) { @@ -3087,7 +3097,8 @@ bool BindingsGenerator::_populate_object_type_interfaces() { enum_proxy_cname = StringName(enum_proxy_name); } EnumInterface ienum(enum_proxy_cname); - const List<StringName> &enum_constants = E.value; + ienum.is_flags = E.value.is_bitfield; + const List<StringName> &enum_constants = E.value.constants; for (const StringName &constant_cname : enum_constants) { String constant_name = constant_cname.operator String(); int64_t *value = class_info->constant_map.getptr(constant_cname); @@ -3213,6 +3224,11 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar r_iarg.default_argument = "new %s" + r_iarg.default_argument; r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; break; + case Variant::VECTOR4: + case Variant::VECTOR4I: + r_iarg.default_argument = "new %s" + r_iarg.default_argument; + r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; + break; case Variant::OBJECT: ERR_FAIL_COND_V_MSG(!p_val.is_zero(), false, "Parameter of type '" + String(r_iarg.type.cname) + "' can only have null/zero as the default value."); @@ -3267,6 +3283,15 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar } r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; } break; + case Variant::PROJECTION: { + Projection transform = p_val.operator Projection(); + if (transform == Projection()) { + r_iarg.default_argument = "Projection.Identity"; + } else { + r_iarg.default_argument = "new Projection(new Vector4" + transform.matrix[0].operator String() + ", new Vector4" + transform.matrix[1].operator String() + ", new Vector4" + transform.matrix[2].operator String() + ", new Vector4" + transform.matrix[3].operator String() + ")"; + } + r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL; + } break; case Variant::BASIS: { Basis basis = p_val.operator Basis(); if (basis == Basis()) { @@ -3676,6 +3701,7 @@ void BindingsGenerator::_populate_global_constants() { if (enum_name != StringName()) { EnumInterface ienum(enum_name); + // TODO: ienum.is_flags is always false for core constants since they don't seem to support bitfield enums List<EnumInterface>::Element *enum_match = global_enums.find(ienum); if (enum_match) { enum_match->get().constants.push_back(iconstant); diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h index 70c4f12146..ee170e4558 100644 --- a/modules/mono/editor/bindings_generator.h +++ b/modules/mono/editor/bindings_generator.h @@ -60,6 +60,7 @@ class BindingsGenerator { struct EnumInterface { StringName cname; List<ConstantInterface> constants; + bool is_flags = false; _FORCE_INLINE_ bool operator==(const EnumInterface &p_ienum) const { return p_ienum.cname == cname; @@ -589,6 +590,9 @@ class BindingsGenerator { StringName type_Vector2 = StaticCString::create("Vector2"); StringName type_Rect2 = StaticCString::create("Rect2"); StringName type_Vector3 = StaticCString::create("Vector3"); + StringName type_Vector3i = StaticCString::create("Vector3i"); + StringName type_Vector4 = StaticCString::create("Vector4"); + StringName type_Vector4i = StaticCString::create("Vector4i"); // Object not included as it must be checked for all derived classes static constexpr int nullable_types_count = 17; diff --git a/modules/mono/editor/editor_internal_calls.cpp b/modules/mono/editor/editor_internal_calls.cpp index f7f710f3f1..5e4fe90553 100644 --- a/modules/mono/editor/editor_internal_calls.cpp +++ b/modules/mono/editor/editor_internal_calls.cpp @@ -47,7 +47,7 @@ #include "../glue/cs_glue_version.gen.h" #include "../godotsharp_dirs.h" #include "../mono_gd/gd_mono_marshal.h" -#include "../utils/osx_utils.h" +#include "../utils/macos_utils.h" #include "code_completion.h" #include "godotsharp_export.h" @@ -188,8 +188,8 @@ MonoString *godot_icall_Internal_UpdateApiAssembliesFromPrebuilt(MonoString *p_c return GDMonoMarshal::mono_string_from_godot(error_str); } -MonoString *godot_icall_Internal_FullTemplatesDir() { - String full_templates_dir = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG); +MonoString *godot_icall_Internal_FullExportTemplatesDir() { + String full_templates_dir = EditorSettings::get_singleton()->get_export_templates_dir().plus_file(VERSION_FULL_CONFIG); return GDMonoMarshal::mono_string_from_godot(full_templates_dir); } @@ -198,10 +198,10 @@ MonoString *godot_icall_Internal_SimplifyGodotPath(MonoString *p_path) { return GDMonoMarshal::mono_string_from_godot(path.simplify_path()); } -MonoBoolean godot_icall_Internal_IsOsxAppBundleInstalled(MonoString *p_bundle_id) { -#ifdef OSX_ENABLED +MonoBoolean godot_icall_Internal_IsMacOSAppBundleInstalled(MonoString *p_bundle_id) { +#ifdef MACOS_ENABLED String bundle_id = GDMonoMarshal::mono_string_to_godot(p_bundle_id); - return (MonoBoolean)osx_is_app_bundle_installed(bundle_id); + return (MonoBoolean)macos_is_app_bundle_installed(bundle_id); #else (void)p_bundle_id; // UNUSED return (MonoBoolean) false; @@ -364,9 +364,9 @@ void register_editor_internal_calls() { // Internals GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_UpdateApiAssembliesFromPrebuilt", godot_icall_Internal_UpdateApiAssembliesFromPrebuilt); - GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_FullTemplatesDir", godot_icall_Internal_FullTemplatesDir); + GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_FullExportTemplatesDir", godot_icall_Internal_FullExportTemplatesDir); GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_SimplifyGodotPath", godot_icall_Internal_SimplifyGodotPath); - GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_IsOsxAppBundleInstalled", godot_icall_Internal_IsOsxAppBundleInstalled); + GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_IsMacOSAppBundleInstalled", godot_icall_Internal_IsMacOSAppBundleInstalled); GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GodotIs32Bits", godot_icall_Internal_GodotIs32Bits); GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GodotIsRealTDouble", godot_icall_Internal_GodotIsRealTDouble); GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GodotMainIteration", godot_icall_Internal_GodotMainIteration); diff --git a/modules/mono/editor/editor_internal_calls.h b/modules/mono/editor/editor_internal_calls.h index a899634d57..8262ac211a 100644 --- a/modules/mono/editor/editor_internal_calls.h +++ b/modules/mono/editor/editor_internal_calls.h @@ -28,9 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef EDITOR_INTERNAL_CALL_H -#define EDITOR_INTERNAL_CALL_H +#ifndef EDITOR_INTERNAL_CALLS_H +#define EDITOR_INTERNAL_CALLS_H void register_editor_internal_calls(); -#endif // EDITOR_INTERNAL_CALL_H +#endif // EDITOR_INTERNAL_CALLS_H diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs new file mode 100644 index 0000000000..0a1c8322d7 --- /dev/null +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttribute.cs @@ -0,0 +1,43 @@ +using System; + +namespace Godot +{ + /// <summary> + /// Attribute that changes the RPC mode for the annotated <c>method</c> to the given <see cref="Mode"/>, + /// optionally specifying the <see cref="TransferMode"/> and <see cref="TransferChannel"/> (on supported peers). + /// See <see cref="RPCMode"/> and <see cref="TransferMode"/>. By default, methods are not exposed to networking + /// (and RPCs). + /// </summary> + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] + public class RPCAttribute : Attribute + { + /// <summary> + /// RPC mode for the annotated method. + /// </summary> + public RPCMode Mode { get; } = RPCMode.Disabled; + + /// <summary> + /// If the method will also be called locally; otherwise, it is only called remotely. + /// </summary> + public bool CallLocal { get; set; } = false; + + /// <summary> + /// Transfer mode for the annotated method. + /// </summary> + public TransferMode TransferMode { get; set; } = TransferMode.Reliable; + + /// <summary> + /// Transfer channel for the annotated mode. + /// </summary> + public int TransferChannel { get; set; } = 0; + + /// <summary> + /// Constructs a <see cref="RPCAttribute"/> instance. + /// </summary> + /// <param name="mode">The RPC mode to use.</param> + public RPCAttribute(RPCMode mode = RPCMode.Authority) + { + Mode = mode; + } + } +} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs deleted file mode 100644 index f0d37c344d..0000000000 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/RPCAttributes.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; - -namespace Godot -{ - /// <summary> - /// Constructs a new AnyPeerAttribute instance. Members with the AnyPeerAttribute are given authority over their own player. - /// </summary> - [AttributeUsage(AttributeTargets.Method)] - public class AnyPeerAttribute : Attribute { } - - /// <summary> - /// Constructs a new AuthorityAttribute instance. Members with the AuthorityAttribute are given authority over the game. - /// </summary> - [AttributeUsage(AttributeTargets.Method)] - public class AuthorityAttribute : Attribute { } -} diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs index 2b820070d6..36b7d0f80f 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs @@ -198,6 +198,28 @@ namespace Godot } /// <summary> + /// Returns the point at the given <paramref name="t"/> on a one-dimensional Bezier curve defined by + /// the given <paramref name="control1"/>, <paramref name="control2"/> and <paramref name="end"/> points. + /// </summary> + /// <param name="start">The start value for the interpolation.</param> + /// <param name="control1">Control point that defines the bezier curve.</param> + /// <param name="control2">Control point that defines the bezier curve.</param> + /// <param name="end">The destination value for the interpolation.</param> + /// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> + /// <returns>The resulting value of the interpolation.</returns> + public static real_t BezierInterpolate(real_t start, real_t control1, real_t control2, real_t end, real_t t) + { + // Formula from Wikipedia article on Bezier curves + real_t omt = 1 - t; + real_t omt2 = omt * omt; + real_t omt3 = omt2 * omt; + real_t t2 = t * t; + real_t t3 = t2 * t; + + return start * omt3 + control1 * omt2 * t * 3 + control2 * omt * t2 * 3 + end * t3; + } + + /// <summary> /// Converts an angle expressed in degrees to radians. /// </summary> /// <param name="deg">An angle expressed in degrees.</param> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs index 40fb5f8788..9ae01016cb 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs @@ -170,6 +170,21 @@ namespace Godot } /// <summary> + /// Returns all names concatenated with a slash character (<c>/</c>). + /// </summary> + /// <example> + /// <code> + /// var nodepath = new NodePath("Path2D/PathFollow2D/Sprite2D:texture:load_path"); + /// GD.Print(nodepath.GetConcatenatedNames()); // Path2D/PathFollow2D/Sprite2D + /// </code> + /// </example> + /// <returns>The names concatenated with <c>/</c>.</returns> + public string GetConcatenatedNames() + { + return godot_icall_NodePath_get_concatenated_names(GetPtr(this)); + } + + /// <summary> /// Returns all subnames concatenated with a colon character (<c>:</c>) /// as separator, i.e. the right side of the first colon in a node path. /// </summary> @@ -269,6 +284,9 @@ namespace Godot private static extern IntPtr godot_icall_NodePath_get_as_property_path(IntPtr ptr); [MethodImpl(MethodImplOptions.InternalCall)] + private static extern string godot_icall_NodePath_get_concatenated_names(IntPtr ptr); + + [MethodImpl(MethodImplOptions.InternalCall)] private static extern string godot_icall_NodePath_get_concatenated_subnames(IntPtr ptr); [MethodImpl(MethodImplOptions.InternalCall)] diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs index 63af1c5892..fd97a71e47 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs @@ -118,15 +118,15 @@ namespace Godot /// <summary> /// Returns <see langword="true"/> if point is inside the plane. - /// Comparison uses a custom minimum epsilon threshold. + /// Comparison uses a custom minimum tolerance threshold. /// </summary> /// <param name="point">The point to check.</param> - /// <param name="epsilon">The tolerance threshold.</param> + /// <param name="tolerance">The tolerance threshold.</param> /// <returns>A <see langword="bool"/> for whether or not the plane has the point.</returns> - public bool HasPoint(Vector3 point, real_t epsilon = Mathf.Epsilon) + public bool HasPoint(Vector3 point, real_t tolerance = Mathf.Epsilon) { real_t dist = _normal.Dot(point) - D; - return Mathf.Abs(dist) <= epsilon; + return Mathf.Abs(dist) <= tolerance; } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs index 89947899cb..e01db7b88c 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs @@ -347,7 +347,7 @@ namespace Godot /// </summary> /// <param name="offset">The offset to translate by.</param> /// <returns>The translated matrix.</returns> - public Transform2D Translated(Vector2 offset) + public Transform2D TranslatedLocal(Vector2 offset) { Transform2D copy = this; copy.origin += copy.BasisXform(offset); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs index 7b211b6577..41565bf680 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs @@ -239,7 +239,7 @@ namespace Godot /// </summary> /// <param name="offset">The offset to translate by.</param> /// <returns>The translated matrix.</returns> - public Transform3D Translated(Vector3 offset) + public Transform3D TranslatedLocal(Vector3 offset) { return new Transform3D(basis, new Vector3 ( diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs index 9e990ce83e..7bdbe1c28b 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs @@ -221,6 +221,27 @@ namespace Godot } /// <summary> + /// Returns the point at the given <paramref name="t"/> on a one-dimensional Bezier curve defined by this vector + /// and the given <paramref name="control1"/>, <paramref name="control2"/> and <paramref name="end"/> points. + /// </summary> + /// <param name="control1">Control point that defines the bezier curve.</param> + /// <param name="control2">Control point that defines the bezier curve.</param> + /// <param name="end">The destination vector.</param> + /// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> + /// <returns>The interpolated vector.</returns> + public Vector2 BezierInterpolate(Vector2 control1, Vector2 control2, Vector2 end, real_t t) + { + // Formula from Wikipedia article on Bezier curves + real_t omt = 1 - t; + real_t omt2 = omt * omt; + real_t omt3 = omt2 * omt; + real_t t2 = t * t; + real_t t3 = t2 * t; + + return this * omt3 + control1 * omt2 * t * 3 + control2 * omt * t2 * 3 + end * t3; + } + + /// <summary> /// Returns the normalized vector pointing from this vector to <paramref name="to"/>. /// </summary> /// <param name="to">The other vector to point towards.</param> @@ -522,9 +543,10 @@ namespace Godot { real_t startLengthSquared = LengthSquared(); real_t endLengthSquared = to.LengthSquared(); - if (startLengthSquared == 0.0 || endLengthSquared == 0.0) { - // Zero length vectors have no angle, so the best we can do is either lerp or throw an error. - return Lerp(to, weight); + if (startLengthSquared == 0.0 || endLengthSquared == 0.0) + { + // Zero length vectors have no angle, so the best we can do is either lerp or throw an error. + return Lerp(to, weight); } real_t startLength = Mathf.Sqrt(startLengthSquared); real_t resultLength = Mathf.Lerp(startLength, Mathf.Sqrt(endLengthSquared), weight); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs index 412a885daa..b61954a84c 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs @@ -461,7 +461,7 @@ namespace Godot } /// <summary> - /// Multiplies each component of the <see cref="Vector2i"/> + /// Divides each component of the <see cref="Vector2i"/> /// by the given <see langword="int"/>. /// </summary> /// <param name="vec">The dividend vector.</param> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs index 56859da7f2..480165d44a 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs @@ -214,6 +214,27 @@ namespace Godot } /// <summary> + /// Returns the point at the given <paramref name="t"/> on a one-dimensional Bezier curve defined by this vector + /// and the given <paramref name="control1"/>, <paramref name="control2"/> and <paramref name="end"/> points. + /// </summary> + /// <param name="control1">Control point that defines the bezier curve.</param> + /// <param name="control2">Control point that defines the bezier curve.</param> + /// <param name="end">The destination vector.</param> + /// <param name="t">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> + /// <returns>The interpolated vector.</returns> + public Vector3 BezierInterpolate(Vector3 control1, Vector3 control2, Vector3 end, real_t t) + { + // Formula from Wikipedia article on Bezier curves + real_t omt = 1 - t; + real_t omt2 = omt * omt; + real_t omt3 = omt2 * omt; + real_t t2 = t * t; + real_t t3 = t2 * t; + + return this * omt3 + control1 * omt2 * t * 3 + control2 * omt * t2 * 3 + end * t3; + } + + /// <summary> /// Returns the normalized vector pointing from this vector to <paramref name="to"/>. /// </summary> /// <param name="to">The other vector to point towards.</param> @@ -562,9 +583,10 @@ namespace Godot { real_t startLengthSquared = LengthSquared(); real_t endLengthSquared = to.LengthSquared(); - if (startLengthSquared == 0.0 || endLengthSquared == 0.0) { - // Zero length vectors have no angle, so the best we can do is either lerp or throw an error. - return Lerp(to, weight); + if (startLengthSquared == 0.0 || endLengthSquared == 0.0) + { + // Zero length vectors have no angle, so the best we can do is either lerp or throw an error. + return Lerp(to, weight); } real_t startLength = Mathf.Sqrt(startLengthSquared); real_t resultLength = Mathf.Lerp(startLength, Mathf.Sqrt(endLengthSquared), weight); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs index abfd2ae720..0d4894f206 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs @@ -449,7 +449,7 @@ namespace Godot } /// <summary> - /// Multiplies each component of the <see cref="Vector3i"/> + /// Divides each component of the <see cref="Vector3i"/> /// by the given <see langword="int"/>. /// </summary> /// <param name="vec">The dividend vector.</param> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj index 1fcfe74c86..e59f45bbf6 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj +++ b/modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj @@ -18,7 +18,7 @@ <Compile Include="Core\Attributes\DisableGodotGeneratorsAttribute.cs" /> <Compile Include="Core\Attributes\ExportAttribute.cs" /> <Compile Include="Core\Attributes\GodotMethodAttribute.cs" /> - <Compile Include="Core\Attributes\RPCAttributes.cs" /> + <Compile Include="Core\Attributes\RPCAttribute.cs" /> <Compile Include="Core\Attributes\ScriptPathAttribute.cs" /> <Compile Include="Core\Attributes\SignalAttribute.cs" /> <Compile Include="Core\Attributes\ToolAttribute.cs" /> diff --git a/modules/mono/glue/glue_header.h b/modules/mono/glue/glue_header.h index 9638b23410..f9ad1a9893 100644 --- a/modules/mono/glue/glue_header.h +++ b/modules/mono/glue/glue_header.h @@ -28,6 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#ifndef GLUE_HEADER_H +#define GLUE_HEADER_H + #ifdef MONO_GLUE_ENABLED #include "../mono_gd/gd_mono_marshal.h" @@ -84,3 +87,5 @@ void godot_register_glue_header_icalls() { #include "arguments_vector.h" #endif // MONO_GLUE_ENABLED + +#endif // GLUE_HEADER_H diff --git a/modules/mono/glue/nodepath_glue.cpp b/modules/mono/glue/nodepath_glue.cpp index 0ea9814b1a..16e1509eb0 100644 --- a/modules/mono/glue/nodepath_glue.cpp +++ b/modules/mono/glue/nodepath_glue.cpp @@ -68,6 +68,10 @@ MonoString *godot_icall_NodePath_get_subname(NodePath *p_ptr, uint32_t p_idx) { return GDMonoMarshal::mono_string_from_godot(p_ptr->get_subname(p_idx)); } +MonoString *godot_icall_NodePath_get_concatenated_names(NodePath *p_ptr) { + return GDMonoMarshal::mono_string_from_godot(p_ptr->get_concatenated_names()); +} + MonoString *godot_icall_NodePath_get_concatenated_subnames(NodePath *p_ptr) { return GDMonoMarshal::mono_string_from_godot(p_ptr->get_concatenated_subnames()); } @@ -85,6 +89,7 @@ void godot_register_nodepath_icalls() { GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_Dtor", godot_icall_NodePath_Dtor); GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_operator_String", godot_icall_NodePath_operator_String); GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_as_property_path", godot_icall_NodePath_get_as_property_path); + GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_concatenated_names", godot_icall_NodePath_get_concatenated_names); GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_concatenated_subnames", godot_icall_NodePath_get_concatenated_subnames); GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_name", godot_icall_NodePath_get_name); GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_name_count", godot_icall_NodePath_get_name_count); diff --git a/modules/mono/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp index cb2b60fcce..f17b24e399 100644 --- a/modules/mono/godotsharp_dirs.cpp +++ b/modules/mono/godotsharp_dirs.cpp @@ -184,7 +184,7 @@ private: data_mono_bin_dir = data_mono_root_dir.plus_file("bin"); #endif -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED if (!DirAccess::exists(data_editor_tools_dir)) { data_editor_tools_dir = exe_dir.plus_file("../Resources/GodotSharp/Tools"); } @@ -222,7 +222,7 @@ private: data_mono_bin_dir = data_mono_root_dir.plus_file("bin"); #endif -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED if (!DirAccess::exists(data_mono_root_dir)) { data_mono_etc_dir = exe_dir.plus_file("../Resources/GodotSharp/Mono/etc"); data_mono_lib_dir = exe_dir.plus_file("../Resources/GodotSharp/Mono/lib"); diff --git a/modules/mono/mono_gc_handle.h b/modules/mono/mono_gc_handle.h index ab9e508c99..e2aff1d19d 100644 --- a/modules/mono/mono_gc_handle.h +++ b/modules/mono/mono_gc_handle.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef CSHARP_GC_HANDLE_H -#define CSHARP_GC_HANDLE_H +#ifndef MONO_GC_HANDLE_H +#define MONO_GC_HANDLE_H #include <mono/jit/jit.h> @@ -104,4 +104,4 @@ public: ~MonoGCHandleRef() { release(); } }; -#endif // CSHARP_GC_HANDLE_H +#endif // MONO_GC_HANDLE_H diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index 39a8ef22b7..d3d3bb2bef 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -55,7 +55,7 @@ #ifdef ANDROID_ENABLED #include "android_mono_config.h" #include "support/android_support.h" -#elif defined(IPHONE_ENABLED) +#elif defined(IOS_ENABLED) #include "support/ios_support.h" #endif @@ -188,7 +188,7 @@ MonoDomain *gd_initialize_mono_runtime() { MonoDomain *gd_initialize_mono_runtime() { gd_mono_debug_init(); -#if defined(IPHONE_ENABLED) || defined(ANDROID_ENABLED) +#if defined(IOS_ENABLED) || defined(ANDROID_ENABLED) // I don't know whether this actually matters or not const char *runtime_version = "mobile"; #else @@ -263,7 +263,7 @@ void GDMono::determine_mono_dirs(String &r_assembly_rootdir, String &r_config_di if (mono_reg_info.config_dir.length() && DirAccess::exists(mono_reg_info.config_dir)) { r_config_dir = mono_reg_info.config_dir; } -#elif defined(OSX_ENABLED) +#elif defined(MACOS_ENABLED) const char *c_assembly_rootdir = mono_assembly_getrootdir(); const char *c_config_dir = mono_get_config_dir(); @@ -343,7 +343,7 @@ void GDMono::initialize() { #if defined(ANDROID_ENABLED) gdmono::android::support::initialize(); -#elif defined(IPHONE_ENABLED) +#elif defined(IOS_ENABLED) gdmono::ios::support::initialize(); #endif diff --git a/modules/mono/mono_gd/gd_mono_cache.cpp b/modules/mono/mono_gd/gd_mono_cache.cpp index 44a8e26b8f..69d8c7edc9 100644 --- a/modules/mono/mono_gd/gd_mono_cache.cpp +++ b/modules/mono/mono_gd/gd_mono_cache.cpp @@ -108,9 +108,12 @@ void CachedData::clear_godot_api_cache() { class_Transform2D = nullptr; class_Vector3 = nullptr; class_Vector3i = nullptr; + class_Vector4 = nullptr; + class_Vector4i = nullptr; class_Basis = nullptr; class_Quaternion = nullptr; class_Transform3D = nullptr; + class_Projection = nullptr; class_AABB = nullptr; class_Color = nullptr; class_Plane = nullptr; @@ -140,8 +143,11 @@ void CachedData::clear_godot_api_cache() { field_ExportAttribute_hintString = nullptr; class_SignalAttribute = nullptr; class_ToolAttribute = nullptr; - class_AnyPeerAttribute = nullptr; - class_AuthorityAttribute = nullptr; + class_RPCAttribute = nullptr; + property_RPCAttribute_Mode = nullptr; + property_RPCAttribute_CallLocal = nullptr; + property_RPCAttribute_TransferMode = nullptr; + property_RPCAttribute_TransferChannel = nullptr; class_GodotMethodAttribute = nullptr; field_GodotMethodAttribute_methodName = nullptr; class_ScriptPathAttribute = nullptr; @@ -236,9 +242,12 @@ void update_godot_api_cache() { CACHE_CLASS_AND_CHECK(Transform2D, GODOT_API_CLASS(Transform2D)); CACHE_CLASS_AND_CHECK(Vector3, GODOT_API_CLASS(Vector3)); CACHE_CLASS_AND_CHECK(Vector3i, GODOT_API_CLASS(Vector3i)); + CACHE_CLASS_AND_CHECK(Vector4, GODOT_API_CLASS(Vector4)); + CACHE_CLASS_AND_CHECK(Vector4i, GODOT_API_CLASS(Vector4i)); CACHE_CLASS_AND_CHECK(Basis, GODOT_API_CLASS(Basis)); CACHE_CLASS_AND_CHECK(Quaternion, GODOT_API_CLASS(Quaternion)); CACHE_CLASS_AND_CHECK(Transform3D, GODOT_API_CLASS(Transform3D)); + CACHE_CLASS_AND_CHECK(Projection, GODOT_API_CLASS(Projection)); CACHE_CLASS_AND_CHECK(AABB, GODOT_API_CLASS(AABB)); CACHE_CLASS_AND_CHECK(Color, GODOT_API_CLASS(Color)); CACHE_CLASS_AND_CHECK(Plane, GODOT_API_CLASS(Plane)); @@ -268,8 +277,11 @@ void update_godot_api_cache() { CACHE_FIELD_AND_CHECK(ExportAttribute, hintString, CACHED_CLASS(ExportAttribute)->get_field("hintString")); CACHE_CLASS_AND_CHECK(SignalAttribute, GODOT_API_CLASS(SignalAttribute)); CACHE_CLASS_AND_CHECK(ToolAttribute, GODOT_API_CLASS(ToolAttribute)); - CACHE_CLASS_AND_CHECK(AnyPeerAttribute, GODOT_API_CLASS(AnyPeerAttribute)); - CACHE_CLASS_AND_CHECK(AuthorityAttribute, GODOT_API_CLASS(AuthorityAttribute)); + CACHE_CLASS_AND_CHECK(RPCAttribute, GODOT_API_CLASS(RPCAttribute)); + CACHE_PROPERTY_AND_CHECK(RPCAttribute, Mode, CACHED_CLASS(RPCAttribute)->get_property("Mode")); + CACHE_PROPERTY_AND_CHECK(RPCAttribute, CallLocal, CACHED_CLASS(RPCAttribute)->get_property("CallLocal")); + CACHE_PROPERTY_AND_CHECK(RPCAttribute, TransferMode, CACHED_CLASS(RPCAttribute)->get_property("TransferMode")); + CACHE_PROPERTY_AND_CHECK(RPCAttribute, TransferChannel, CACHED_CLASS(RPCAttribute)->get_property("TransferChannel")); CACHE_CLASS_AND_CHECK(GodotMethodAttribute, GODOT_API_CLASS(GodotMethodAttribute)); CACHE_FIELD_AND_CHECK(GodotMethodAttribute, methodName, CACHED_CLASS(GodotMethodAttribute)->get_field("methodName")); CACHE_CLASS_AND_CHECK(ScriptPathAttribute, GODOT_API_CLASS(ScriptPathAttribute)); diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h index 92136e1f41..e9cc26899e 100644 --- a/modules/mono/mono_gd/gd_mono_cache.h +++ b/modules/mono/mono_gd/gd_mono_cache.h @@ -79,9 +79,12 @@ struct CachedData { GDMonoClass *class_Transform2D = nullptr; GDMonoClass *class_Vector3 = nullptr; GDMonoClass *class_Vector3i = nullptr; + GDMonoClass *class_Vector4 = nullptr; + GDMonoClass *class_Vector4i = nullptr; GDMonoClass *class_Basis = nullptr; GDMonoClass *class_Quaternion = nullptr; GDMonoClass *class_Transform3D = nullptr; + GDMonoClass *class_Projection = nullptr; GDMonoClass *class_AABB = nullptr; GDMonoClass *class_Color = nullptr; GDMonoClass *class_Plane = nullptr; @@ -111,8 +114,11 @@ struct CachedData { GDMonoField *field_ExportAttribute_hintString = nullptr; GDMonoClass *class_SignalAttribute = nullptr; GDMonoClass *class_ToolAttribute = nullptr; - GDMonoClass *class_AnyPeerAttribute = nullptr; - GDMonoClass *class_AuthorityAttribute = nullptr; + GDMonoClass *class_RPCAttribute = nullptr; + GDMonoProperty *property_RPCAttribute_Mode = nullptr; + GDMonoProperty *property_RPCAttribute_CallLocal = nullptr; + GDMonoProperty *property_RPCAttribute_TransferMode = nullptr; + GDMonoProperty *property_RPCAttribute_TransferChannel = nullptr; GDMonoClass *class_GodotMethodAttribute = nullptr; GDMonoField *field_GodotMethodAttribute_methodName = nullptr; GDMonoClass *class_ScriptPathAttribute = nullptr; diff --git a/modules/mono/mono_gd/gd_mono_field.cpp b/modules/mono/mono_gd/gd_mono_field.cpp index 333a06c94a..cb025fc67a 100644 --- a/modules/mono/mono_gd/gd_mono_field.cpp +++ b/modules/mono/mono_gd/gd_mono_field.cpp @@ -140,6 +140,18 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ break; } + if (tclass == CACHED_CLASS(Vector4)) { + GDMonoMarshal::M_Vector4 from = MARSHALLED_OUT(Vector4, p_value.operator ::Vector4()); + mono_field_set_value(p_object, mono_field, &from); + break; + } + + if (tclass == CACHED_CLASS(Vector4i)) { + GDMonoMarshal::M_Vector4i from = MARSHALLED_OUT(Vector4i, p_value.operator ::Vector4i()); + mono_field_set_value(p_object, mono_field, &from); + break; + } + if (tclass == CACHED_CLASS(Basis)) { GDMonoMarshal::M_Basis from = MARSHALLED_OUT(Basis, p_value.operator ::Basis()); mono_field_set_value(p_object, mono_field, &from); @@ -158,6 +170,12 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ break; } + if (tclass == CACHED_CLASS(Projection)) { + GDMonoMarshal::M_Projection from = MARSHALLED_OUT(Projection, p_value.operator ::Projection()); + mono_field_set_value(p_object, mono_field, &from); + break; + } + if (tclass == CACHED_CLASS(AABB)) { GDMonoMarshal::M_AABB from = MARSHALLED_OUT(AABB, p_value.operator ::AABB()); mono_field_set_value(p_object, mono_field, &from); @@ -328,6 +346,14 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ GDMonoMarshal::M_Vector3i from = MARSHALLED_OUT(Vector3i, p_value.operator ::Vector3i()); mono_field_set_value(p_object, mono_field, &from); } break; + case Variant::VECTOR4: { + GDMonoMarshal::M_Vector4 from = MARSHALLED_OUT(Vector4, p_value.operator ::Vector4()); + mono_field_set_value(p_object, mono_field, &from); + } break; + case Variant::VECTOR4I: { + GDMonoMarshal::M_Vector4i from = MARSHALLED_OUT(Vector4i, p_value.operator ::Vector4i()); + mono_field_set_value(p_object, mono_field, &from); + } break; case Variant::TRANSFORM2D: { GDMonoMarshal::M_Transform2D from = MARSHALLED_OUT(Transform2D, p_value.operator ::Transform2D()); mono_field_set_value(p_object, mono_field, &from); @@ -352,6 +378,10 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ GDMonoMarshal::M_Transform3D from = MARSHALLED_OUT(Transform3D, p_value.operator ::Transform3D()); mono_field_set_value(p_object, mono_field, &from); } break; + case Variant::PROJECTION: { + GDMonoMarshal::M_Projection from = MARSHALLED_OUT(Projection, p_value.operator ::Projection()); + mono_field_set_value(p_object, mono_field, &from); + } break; case Variant::COLOR: { GDMonoMarshal::M_Color from = MARSHALLED_OUT(Color, p_value.operator ::Color()); mono_field_set_value(p_object, mono_field, &from); diff --git a/modules/mono/mono_gd/gd_mono_field.h b/modules/mono/mono_gd/gd_mono_field.h index 87ef245f3f..1d30f7a369 100644 --- a/modules/mono/mono_gd/gd_mono_field.h +++ b/modules/mono/mono_gd/gd_mono_field.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GDMONOFIELD_H -#define GDMONOFIELD_H +#ifndef GD_MONO_FIELD_H +#define GD_MONO_FIELD_H #include "gd_mono.h" #include "gd_mono_header.h" @@ -75,4 +75,4 @@ public: ~GDMonoField(); }; -#endif // GDMONOFIELD_H +#endif // GD_MONO_FIELD_H diff --git a/modules/mono/mono_gd/gd_mono_log.h b/modules/mono/mono_gd/gd_mono_log.h index 9fc35f8e31..93ba6a410e 100644 --- a/modules/mono/mono_gd/gd_mono_log.h +++ b/modules/mono/mono_gd/gd_mono_log.h @@ -35,7 +35,7 @@ #include "core/typedefs.h" -#if !defined(JAVASCRIPT_ENABLED) && !defined(IPHONE_ENABLED) +#if !defined(JAVASCRIPT_ENABLED) && !defined(IOS_ENABLED) // We have custom mono log callbacks for WASM and iOS #define GD_MONO_LOG_ENABLED #endif diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp index 957abca37b..a860442764 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.cpp +++ b/modules/mono/mono_gd/gd_mono_marshal.cpp @@ -99,6 +99,13 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_ if (vtclass == CACHED_CLASS(Vector3i)) { return Variant::VECTOR3I; } + if (vtclass == CACHED_CLASS(Vector4)) { + return Variant::VECTOR4; + } + + if (vtclass == CACHED_CLASS(Vector4i)) { + return Variant::VECTOR4I; + } if (vtclass == CACHED_CLASS(Basis)) { return Variant::BASIS; @@ -111,7 +118,9 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_ if (vtclass == CACHED_CLASS(Transform3D)) { return Variant::TRANSFORM3D; } - + if (vtclass == CACHED_CLASS(Projection)) { + return Variant::PROJECTION; + } if (vtclass == CACHED_CLASS(AABB)) { return Variant::AABB; } @@ -539,6 +548,14 @@ MonoObject *variant_to_mono_object(const Variant &p_var) { GDMonoMarshal::M_Transform2D from = MARSHALLED_OUT(Transform2D, p_var.operator ::Transform2D()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Transform2D), &from); } + case Variant::VECTOR4: { + GDMonoMarshal::M_Vector4 from = MARSHALLED_OUT(Vector4, p_var.operator ::Vector4()); + return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Vector4), &from); + } + case Variant::VECTOR4I: { + GDMonoMarshal::M_Vector4i from = MARSHALLED_OUT(Vector4i, p_var.operator ::Vector4i()); + return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Vector4i), &from); + } case Variant::PLANE: { GDMonoMarshal::M_Plane from = MARSHALLED_OUT(Plane, p_var.operator ::Plane()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Plane), &from); @@ -559,6 +576,10 @@ MonoObject *variant_to_mono_object(const Variant &p_var) { GDMonoMarshal::M_Transform3D from = MARSHALLED_OUT(Transform3D, p_var.operator ::Transform3D()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Transform3D), &from); } + case Variant::PROJECTION: { + GDMonoMarshal::M_Projection from = MARSHALLED_OUT(Projection, p_var.operator ::Projection()); + return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Projection), &from); + } case Variant::COLOR: { GDMonoMarshal::M_Color from = MARSHALLED_OUT(Color, p_var.operator ::Color()); return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(Color), &from); diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h index 778e52b6cb..3b6fd25d71 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.h +++ b/modules/mono/mono_gd/gd_mono_marshal.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GDMONOMARSHAL_H -#define GDMONOMARSHAL_H +#ifndef GD_MONO_MARSHAL_H +#define GD_MONO_MARSHAL_H #include "core/variant/variant.h" @@ -256,6 +256,18 @@ enum { offsetof(Vector3, y) == (sizeof(real_t) * 1) && offsetof(Vector3, z) == (sizeof(real_t) * 2)), + MATCHES_Vector4 = (MATCHES_real_t && (sizeof(Vector4) == (sizeof(real_t) * 4)) && + offsetof(Vector4, x) == (sizeof(real_t) * 0) && + offsetof(Vector4, y) == (sizeof(real_t) * 1) && + offsetof(Vector4, z) == (sizeof(real_t) * 2) && + offsetof(Vector4, w) == (sizeof(real_t) * 3)), + + MATCHES_Vector4i = (MATCHES_int && (sizeof(Vector4i) == (sizeof(int32_t) * 4i)) && + offsetof(Vector4i, x) == (sizeof(int32_t) * 0) && + offsetof(Vector4i, y) == (sizeof(int32_t) * 1) && + offsetof(Vector4i, z) == (sizeof(int32_t) * 2) && + offsetof(Vector4i, w) == (sizeof(int32_t) * 3)), + MATCHES_Vector3i = (MATCHES_int && (sizeof(Vector3i) == (sizeof(int32_t) * 3)) && offsetof(Vector3i, x) == (sizeof(int32_t) * 0) && offsetof(Vector3i, y) == (sizeof(int32_t) * 1) && @@ -273,6 +285,8 @@ enum { offsetof(Transform3D, basis) == 0 && offsetof(Transform3D, origin) == sizeof(Basis)), + MATCHES_Projection = (MATCHES_Vector4 && (sizeof(Projection) == (sizeof(Vector4) * 4))), + MATCHES_AABB = (MATCHES_Vector3 && (sizeof(AABB) == (sizeof(Vector3) * 2)) && offsetof(AABB, position) == (sizeof(Vector3) * 0) && offsetof(AABB, size) == (sizeof(Vector3) * 1)), @@ -291,9 +305,9 @@ enum { // In the future we may force this if we want to ref return these structs #ifdef GD_MONO_FORCE_INTEROP_STRUCT_COPY /* clang-format off */ -static_assert(MATCHES_Vector2 && MATCHES_Rect2 && MATCHES_Transform2D && MATCHES_Vector3 && - MATCHES_Basis && MATCHES_Quaternion && MATCHES_Transform3D && MATCHES_AABB && MATCHES_Color && - MATCHES_Plane && MATCHES_Vector2i && MATCHES_Rect2i && MATCHES_Vector3i); +static_assert(MATCHES_Vector2 && MATCHES_Rect2 && MATCHES_Transform2D && MATCHES_Vector3 && MATCHES_Vector4 && + MATCHES_Basis && MATCHES_Quaternion && MATCHES_Transform3D && MATCHES_Projection && MATCHES_AABB && MATCHES_Color && + MATCHES_Plane && MATCHES_Vector2i && MATCHES_Rect2i && MATCHES_Vector3i && MATCHES_Vector4i); /* clang-format on */ #endif } // namespace InteropLayout @@ -401,6 +415,32 @@ struct M_Vector3i { } }; +struct M_Vector4 { + real_t x, y, z, w; + + static _FORCE_INLINE_ Vector4 convert_to(const M_Vector4 &p_from) { + return Vector4(p_from.x, p_from.y, p_from.z, p_from.w); + } + + static _FORCE_INLINE_ M_Vector4 convert_from(const Vector4 &p_from) { + M_Vector4 ret = { p_from.x, p_from.y, p_from.z, p_from.w }; + return ret; + } +}; + +struct M_Vector4i { + int32_t x, y, z, w; + + static _FORCE_INLINE_ Vector4i convert_to(const M_Vector4i &p_from) { + return Vector4i(p_from.x, p_from.y, p_from.z, p_from.w); + } + + static _FORCE_INLINE_ M_Vector4i convert_from(const Vector4i &p_from) { + M_Vector4i ret = { p_from.x, p_from.y, p_from.z, p_from.w }; + return ret; + } +}; + struct M_Basis { M_Vector3 elements[3]; @@ -447,6 +487,22 @@ struct M_Transform3D { } }; +struct M_Projection { + M_Vector4 vec1; + M_Vector4 vec2; + M_Vector4 vec3; + M_Vector4 vec4; + + static _FORCE_INLINE_ Projection convert_to(const M_Projection &p_from) { + return Projection(M_Vector4::convert_to(p_from.vec1), M_Vector4::convert_to(p_from.vec2), M_Vector4::convert_to(p_from.vec3), M_Vector4::convert_to(p_from.vec4)); + } + + static _FORCE_INLINE_ M_Projection convert_from(const Projection &p_from) { + M_Projection ret = { M_Vector4::convert_from(p_from.matrix[0]), M_Vector4::convert_from(p_from.matrix[1]), M_Vector4::convert_from(p_from.matrix[2]), M_Vector4::convert_from(p_from.matrix[3]) }; + return ret; + } +}; + struct M_AABB { M_Vector3 position; M_Vector3 size; @@ -533,8 +589,11 @@ DECL_TYPE_MARSHAL_TEMPLATES(Transform2D) DECL_TYPE_MARSHAL_TEMPLATES(Vector3) DECL_TYPE_MARSHAL_TEMPLATES(Vector3i) DECL_TYPE_MARSHAL_TEMPLATES(Basis) +DECL_TYPE_MARSHAL_TEMPLATES(Vector4) +DECL_TYPE_MARSHAL_TEMPLATES(Vector4i) DECL_TYPE_MARSHAL_TEMPLATES(Quaternion) DECL_TYPE_MARSHAL_TEMPLATES(Transform3D) +DECL_TYPE_MARSHAL_TEMPLATES(Projection) DECL_TYPE_MARSHAL_TEMPLATES(AABB) DECL_TYPE_MARSHAL_TEMPLATES(Color) DECL_TYPE_MARSHAL_TEMPLATES(Plane) @@ -543,4 +602,4 @@ DECL_TYPE_MARSHAL_TEMPLATES(Plane) #define MARSHALLED_OUT(m_type, m_from) (GDMonoMarshal::marshalled_out_##m_type(m_from)) } // namespace GDMonoMarshal -#endif // GDMONOMARSHAL_H +#endif // GD_MONO_MARSHAL_H diff --git a/modules/mono/mono_gd/gd_mono_method_thunk.h b/modules/mono/mono_gd/gd_mono_method_thunk.h index bb163b89bc..0180dee3ea 100644 --- a/modules/mono/mono_gd/gd_mono_method_thunk.h +++ b/modules/mono/mono_gd/gd_mono_method_thunk.h @@ -39,7 +39,7 @@ #include "gd_mono_method.h" #include "gd_mono_utils.h" -#if !defined(JAVASCRIPT_ENABLED) && !defined(IPHONE_ENABLED) +#if !defined(JAVASCRIPT_ENABLED) && !defined(IOS_ENABLED) #define HAVE_METHOD_THUNKS #endif diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h index 246a1cd31e..300cacfa4b 100644 --- a/modules/mono/mono_gd/gd_mono_utils.h +++ b/modules/mono/mono_gd/gd_mono_utils.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GD_MONOUTILS_H -#define GD_MONOUTILS_H +#ifndef GD_MONO_UTILS_H +#define GD_MONO_UTILS_H #include <mono/metadata/threads.h> @@ -202,4 +202,4 @@ void add_internal_call(const char *p_name, R (*p_func)(P...)) { #define GD_MONO_ASSERT_THREAD_ATTACHED ((void)0) #endif -#endif // GD_MONOUTILS_H +#endif // GD_MONO_UTILS_H diff --git a/modules/mono/mono_gd/support/ios_support.h b/modules/mono/mono_gd/support/ios_support.h index 2f444d5089..03e86df698 100644 --- a/modules/mono/mono_gd/support/ios_support.h +++ b/modules/mono/mono_gd/support/ios_support.h @@ -31,7 +31,7 @@ #ifndef IOS_SUPPORT_H #define IOS_SUPPORT_H -#if defined(IPHONE_ENABLED) +#if defined(IOS_ENABLED) #include "core/string/ustring.h" @@ -45,6 +45,6 @@ void cleanup(); } // namespace ios } // namespace gdmono -#endif // IPHONE_ENABLED +#endif // IOS_ENABLED #endif // IOS_SUPPORT_H diff --git a/modules/mono/mono_gd/support/ios_support.mm b/modules/mono/mono_gd/support/ios_support.mm index df97dfba49..7c941b9d1e 100644 --- a/modules/mono/mono_gd/support/ios_support.mm +++ b/modules/mono/mono_gd/support/ios_support.mm @@ -30,7 +30,7 @@ #include "ios_support.h" -#if defined(IPHONE_ENABLED) +#if defined(IOS_ENABLED) #import <Foundation/Foundation.h> #include <os/log.h> @@ -147,4 +147,4 @@ GD_PINVOKE_EXPORT void xamarin_start_wwan(const char *p_uri) { os_log_error(OS_LOG_DEFAULT, "Not implemented: 'xamarin_start_wwan'"); } -#endif // IPHONE_ENABLED +#endif // IOS_ENABLED diff --git a/modules/mono/utils/osx_utils.cpp b/modules/mono/utils/macos_utils.cpp index abb59420eb..cd4f7a827e 100644 --- a/modules/mono/utils/osx_utils.cpp +++ b/modules/mono/utils/macos_utils.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* osx_utils.cpp */ +/* macos_utils.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,16 +28,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "osx_utils.h" +#include "macos_utils.h" -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED #include "core/string/print_string.h" #import <CoreFoundation/CoreFoundation.h> #import <CoreServices/CoreServices.h> -bool osx_is_app_bundle_installed(const String &p_bundle_id) { +bool macos_is_app_bundle_installed(const String &p_bundle_id) { CFStringRef bundle_id = CFStringCreateWithCString(nullptr, p_bundle_id.utf8(), kCFStringEncodingUTF8); CFArrayRef result = LSCopyApplicationURLsForBundleIdentifier(bundle_id, nullptr); CFRelease(bundle_id); diff --git a/modules/mono/utils/osx_utils.h b/modules/mono/utils/macos_utils.h index 2f6c6dad51..ca4957f5a7 100644 --- a/modules/mono/utils/osx_utils.h +++ b/modules/mono/utils/macos_utils.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* osx_utils.h */ +/* macos_utils.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -30,13 +30,13 @@ #include "core/string/ustring.h" -#ifndef OSX_UTILS_H -#define OSX_UTILS_H +#ifndef MONO_MACOS_UTILS_H +#define MONO_MACOS_UTILS_H -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED -bool osx_is_app_bundle_installed(const String &p_bundle_id); +bool macos_is_app_bundle_installed(const String &p_bundle_id); #endif -#endif // OSX_UTILS_H +#endif // MONO_MACOS_UTILS_H diff --git a/modules/mono/utils/macros.h b/modules/mono/utils/macros.h index 2ca1a4cbf1..b7bd9a2495 100644 --- a/modules/mono/utils/macros.h +++ b/modules/mono/utils/macros.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef UTIL_MACROS_H -#define UTIL_MACROS_H +#ifndef MONO_MACROS_H +#define MONO_MACROS_H #define _GD_VARNAME_CONCAT_B_(m_ignore, m_name) m_name #define _GD_VARNAME_CONCAT_A_(m_a, m_b, m_c) _GD_VARNAME_CONCAT_B_(hello there, m_a##m_b##m_c) @@ -69,4 +69,4 @@ public: #define SCOPE_EXIT \ auto GD_UNIQUE_NAME(gd_scope_exit) = gdmono::ScopeExitAux() + [=]() -> void -#endif // UTIL_MACROS_H +#endif // MONO_MACROS_H diff --git a/modules/mono/utils/path_utils.cpp b/modules/mono/utils/path_utils.cpp index 15a0b28181..a1905dfcfe 100644 --- a/modules/mono/utils/path_utils.cpp +++ b/modules/mono/utils/path_utils.cpp @@ -62,7 +62,8 @@ String cwd() { } String result; - if (result.parse_utf16(buffer.ptr())) { + result.parse_utf16(buffer.ptr()); + if (result.is_empty()) { return "."; } return result.simplify_path(); @@ -73,7 +74,7 @@ String cwd() { } String result; - if (result.parse_utf8(buffer)) { + if (result.parse_utf8(buffer) != OK) { return "."; } @@ -114,7 +115,8 @@ String realpath(const String &p_path) { ::CloseHandle(hFile); String result; - if (result.parse_utf16(buffer.ptr())) { + result.parse_utf16(buffer.ptr()); + if (result.is_empty()) { return p_path; } @@ -127,10 +129,10 @@ String realpath(const String &p_path) { } String result; - bool parse_ok = result.parse_utf8(resolved_path); + Error parse_ok = result.parse_utf8(resolved_path); ::free(resolved_path); - if (parse_ok) { + if (parse_ok != OK) { return p_path; } diff --git a/modules/mono/utils/path_utils.h b/modules/mono/utils/path_utils.h index a8cd8daf04..9a2c757361 100644 --- a/modules/mono/utils/path_utils.h +++ b/modules/mono/utils/path_utils.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef PATH_UTILS_H -#define PATH_UTILS_H +#ifndef MONO_PATH_UTILS_H +#define MONO_PATH_UTILS_H #include "core/string/string_builder.h" #include "core/string/ustring.h" @@ -58,4 +58,4 @@ String realpath(const String &p_path); String relative_to(const String &p_path, const String &p_relative_to); } // namespace path -#endif // PATH_UTILS_H +#endif // MONO_PATH_UTILS_H diff --git a/modules/mono/utils/string_utils.cpp b/modules/mono/utils/string_utils.cpp index 64b68b70af..975f2d8332 100644 --- a/modules/mono/utils/string_utils.cpp +++ b/modules/mono/utils/string_utils.cpp @@ -178,7 +178,7 @@ Error read_all_file_utf8(const String &p_path, String &r_content) { w[len] = 0; String source; - if (source.parse_utf8((const char *)w)) { + if (source.parse_utf8((const char *)w) != OK) { ERR_FAIL_V(ERR_INVALID_DATA); } diff --git a/modules/mono/utils/string_utils.h b/modules/mono/utils/string_utils.h index d79888716a..fa4c5e89f4 100644 --- a/modules/mono/utils/string_utils.h +++ b/modules/mono/utils/string_utils.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef STRING_FORMAT_H -#define STRING_FORMAT_H +#ifndef MONO_STRING_UTILS_H +#define MONO_STRING_UTILS_H #include "core/string/ustring.h" #include "core/variant/variant.h" @@ -59,4 +59,4 @@ String str_format(const char *p_format, va_list p_list) _PRINTF_FORMAT_ATTRIBUTE char *str_format_new(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_1_2; char *str_format_new(const char *p_format, va_list p_list) _PRINTF_FORMAT_ATTRIBUTE_1_0; -#endif // STRING_FORMAT_H +#endif // MONO_STRING_UTILS_H diff --git a/modules/navigation/nav_map.cpp b/modules/navigation/nav_map.cpp index 17d6e0a0a1..46daa54239 100644 --- a/modules/navigation/nav_map.cpp +++ b/modules/navigation/nav_map.cpp @@ -30,9 +30,9 @@ #include "nav_map.h" +#include "core/object/worker_thread_pool.h" #include "nav_region.h" #include "rvo_agent.h" - #include <algorithm> #define THREE_POINTS_CROSS_PRODUCT(m_a, m_b, m_c) (((m_c) - (m_a)).cross((m_b) - (m_a))) @@ -683,14 +683,8 @@ void NavMap::compute_single_step(uint32_t index, RvoAgent **agent) { void NavMap::step(real_t p_deltatime) { deltatime = p_deltatime; if (controlled_agents.size() > 0) { - if (step_work_pool.get_thread_count() == 0) { - step_work_pool.init(); - } - step_work_pool.do_work( - controlled_agents.size(), - this, - &NavMap::compute_single_step, - controlled_agents.data()); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &NavMap::compute_single_step, controlled_agents.data(), controlled_agents.size(), -1, true, SNAME("NavigationMapAgents")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); } } @@ -736,5 +730,4 @@ NavMap::NavMap() { } NavMap::~NavMap() { - step_work_pool.finish(); } diff --git a/modules/navigation/nav_map.h b/modules/navigation/nav_map.h index 2036dbecd7..98a5c24b3e 100644 --- a/modules/navigation/nav_map.h +++ b/modules/navigation/nav_map.h @@ -34,8 +34,8 @@ #include "nav_rid.h" #include "core/math/math_defs.h" +#include "core/object/worker_thread_pool.h" #include "core/templates/rb_map.h" -#include "core/templates/thread_work_pool.h" #include "nav_utils.h" #include <KdTree.h> @@ -81,9 +81,6 @@ class NavMap : public NavRid { /// Change the id each time the map is updated. uint32_t map_update_id = 0; - /// Pooled threads for computing steps - ThreadWorkPool step_work_pool; - public: NavMap(); ~NavMap(); diff --git a/modules/noise/editor/noise_editor_plugin.cpp b/modules/noise/editor/noise_editor_plugin.cpp index 32c3f0aad4..27a86f45b5 100644 --- a/modules/noise/editor/noise_editor_plugin.cpp +++ b/modules/noise/editor/noise_editor_plugin.cpp @@ -54,7 +54,7 @@ public: set_custom_minimum_size(Size2(0, EDSCALE * PREVIEW_HEIGHT)); _texture_rect = memnew(TextureRect); - _texture_rect->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + _texture_rect->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); _texture_rect->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_COVERED); add_child(_texture_rect); diff --git a/modules/ogg/ogg_packet_sequence.cpp b/modules/ogg/ogg_packet_sequence.cpp index da52ecfdd5..e18fa9e590 100644 --- a/modules/ogg/ogg_packet_sequence.cpp +++ b/modules/ogg/ogg_packet_sequence.cpp @@ -106,7 +106,7 @@ float OGGPacketSequence::get_length() const { return granule_pos / sampling_rate; } -Ref<OGGPacketSequencePlayback> OGGPacketSequence::instance_playback() { +Ref<OGGPacketSequencePlayback> OGGPacketSequence::instantiate_playback() { Ref<OGGPacketSequencePlayback> playback; playback.instantiate(); playback->ogg_packet_sequence = Ref<OGGPacketSequence>(this); diff --git a/modules/ogg/ogg_packet_sequence.h b/modules/ogg/ogg_packet_sequence.h index 73e3cb4fff..76b673c6ac 100644 --- a/modules/ogg/ogg_packet_sequence.h +++ b/modules/ogg/ogg_packet_sequence.h @@ -86,7 +86,7 @@ public: // Returns the granule position of the last page in this sequence. int64_t get_final_granule_pos() const; - Ref<OGGPacketSequencePlayback> instance_playback(); + Ref<OGGPacketSequencePlayback> instantiate_playback(); OGGPacketSequence() {} virtual ~OGGPacketSequence() {} diff --git a/modules/openxr/SCsub b/modules/openxr/SCsub index 8783e061d2..593d1ff3c1 100644 --- a/modules/openxr/SCsub +++ b/modules/openxr/SCsub @@ -35,7 +35,11 @@ if env["platform"] == "android": # may need to include java parts of the openxr loader elif env["platform"] == "linuxbsd": - env_thirdparty.AppendUnique(CPPDEFINES=["XR_OS_LINUX", "XR_USE_PLATFORM_XLIB"]) + env_thirdparty.AppendUnique(CPPDEFINES=["XR_OS_LINUX"]) + + if env["x11"]: + env_thirdparty.AppendUnique(CPPDEFINES=["XR_USE_PLATFORM_XLIB"]) + # FIXME: Review what needs to be set for Android and macOS. env_thirdparty.AppendUnique(CPPDEFINES=["HAVE_SECURE_GETENV"]) elif env["platform"] == "windows": diff --git a/modules/openxr/action_map/openxr_action.h b/modules/openxr/action_map/openxr_action.h index 5e57f89133..a7c1c9988c 100644 --- a/modules/openxr/action_map/openxr_action.h +++ b/modules/openxr/action_map/openxr_action.h @@ -84,4 +84,4 @@ public: VARIANT_ENUM_CAST(OpenXRAction::ActionType); -#endif // !OPENXR_ACTION_H +#endif // OPENXR_ACTION_H diff --git a/modules/openxr/action_map/openxr_action_map.h b/modules/openxr/action_map/openxr_action_map.h index dcd8fc71aa..8659cd3942 100644 --- a/modules/openxr/action_map/openxr_action_map.h +++ b/modules/openxr/action_map/openxr_action_map.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef OPENXR_ACTION_SETS_H -#define OPENXR_ACTION_SETS_H +#ifndef OPENXR_ACTION_MAP_H +#define OPENXR_ACTION_MAP_H #include "core/io/resource.h" @@ -79,4 +79,4 @@ public: ~OpenXRActionMap(); }; -#endif // !OPENXR_ACTION_SETS_H +#endif // OPENXR_ACTION_MAP_H diff --git a/modules/openxr/action_map/openxr_action_set.h b/modules/openxr/action_map/openxr_action_set.h index b1d7168894..2ef7ba4c32 100644 --- a/modules/openxr/action_map/openxr_action_set.h +++ b/modules/openxr/action_map/openxr_action_set.h @@ -72,4 +72,4 @@ public: ~OpenXRActionSet(); }; -#endif // !OPENXR_ACTION_SET_H +#endif // OPENXR_ACTION_SET_H diff --git a/modules/openxr/action_map/openxr_defs.h b/modules/openxr/action_map/openxr_defs.h index 9bdd9a6ded..446e6eb9c6 100644 --- a/modules/openxr/action_map/openxr_defs.h +++ b/modules/openxr/action_map/openxr_defs.h @@ -121,4 +121,4 @@ public: static PackedStringArray get_interaction_profile_paths(); }; -#endif // !OPENXR_DEFS_H +#endif // OPENXR_DEFS_H diff --git a/modules/openxr/action_map/openxr_interaction_profile.cpp b/modules/openxr/action_map/openxr_interaction_profile.cpp index 342c36cdff..99d7a17acf 100644 --- a/modules/openxr/action_map/openxr_interaction_profile.cpp +++ b/modules/openxr/action_map/openxr_interaction_profile.cpp @@ -40,7 +40,7 @@ void OpenXRIPBinding::_bind_methods() { ClassDB::bind_method(D_METHOD("get_paths"), &OpenXRIPBinding::get_paths); ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "paths", PROPERTY_HINT_ARRAY_TYPE, "STRING"), "set_paths", "get_paths"); - ClassDB::bind_method(D_METHOD("has_path"), &OpenXRIPBinding::has_path); + ClassDB::bind_method(D_METHOD("has_path", "path"), &OpenXRIPBinding::has_path); ClassDB::bind_method(D_METHOD("add_path", "path"), &OpenXRIPBinding::add_path); ClassDB::bind_method(D_METHOD("remove_path", "path"), &OpenXRIPBinding::remove_path); } diff --git a/modules/openxr/action_map/openxr_interaction_profile.h b/modules/openxr/action_map/openxr_interaction_profile.h index 46b1bda50f..c77fd490bb 100644 --- a/modules/openxr/action_map/openxr_interaction_profile.h +++ b/modules/openxr/action_map/openxr_interaction_profile.h @@ -98,4 +98,4 @@ public: ~OpenXRInteractionProfile(); }; -#endif // !OPENXR_INTERACTION_PROFILE_H +#endif // OPENXR_INTERACTION_PROFILE_H diff --git a/modules/openxr/doc_classes/OpenXRIPBinding.xml b/modules/openxr/doc_classes/OpenXRIPBinding.xml index 9e1176874a..f96637f2f5 100644 --- a/modules/openxr/doc_classes/OpenXRIPBinding.xml +++ b/modules/openxr/doc_classes/OpenXRIPBinding.xml @@ -24,7 +24,7 @@ </method> <method name="has_path" qualifiers="const"> <return type="bool" /> - <argument index="0" name="arg0" type="String" /> + <argument index="0" name="path" type="String" /> <description> Returns [code]true[/code] if this input/output path is part of this binding. </description> diff --git a/modules/openxr/doc_classes/OpenXRInterface.xml b/modules/openxr/doc_classes/OpenXRInterface.xml index 74f708bc95..25bf496de9 100644 --- a/modules/openxr/doc_classes/OpenXRInterface.xml +++ b/modules/openxr/doc_classes/OpenXRInterface.xml @@ -5,10 +5,10 @@ </brief_description> <description> The OpenXR interface allows Godot to interact with OpenXR runtimes and make it possible to create XR experiences and games. - Due to the needs of OpenXR this interface works slightly different then other plugin based XR interfaces. It needs to be initialised when Godot starts. You need to enable OpenXR, settings for this can be found in your games project settings under the XR heading. You do need to mark a viewport for use with XR in order for Godot to know which render result should be output to the headset. + Due to the needs of OpenXR this interface works slightly different than other plugin based XR interfaces. It needs to be initialised when Godot starts. You need to enable OpenXR, settings for this can be found in your games project settings under the XR heading. You do need to mark a viewport for use with XR in order for Godot to know which render result should be output to the headset. </description> <tutorials> - <link title="OpenXR documentation">$DOCS_URL/tutorials/vr/openxr/index.html</link> + <link title="Setting up XR">$DOCS_URL/tutorials/xr/setting_up_xr.html</link> </tutorials> <signals> <signal name="pose_recentered"> diff --git a/modules/openxr/editor/openxr_action_editor.h b/modules/openxr/editor/openxr_action_editor.h index 6e1b7ab779..6cf098cf08 100644 --- a/modules/openxr/editor/openxr_action_editor.h +++ b/modules/openxr/editor/openxr_action_editor.h @@ -64,4 +64,4 @@ public: OpenXRActionEditor(Ref<OpenXRAction> p_action); }; -#endif // !OPENXR_ACTION_EDITOR_H +#endif // OPENXR_ACTION_EDITOR_H diff --git a/modules/openxr/editor/openxr_action_map_editor.h b/modules/openxr/editor/openxr_action_map_editor.h index dfc941b500..a19bc90f56 100644 --- a/modules/openxr/editor/openxr_action_map_editor.h +++ b/modules/openxr/editor/openxr_action_map_editor.h @@ -97,4 +97,4 @@ public: ~OpenXRActionMapEditor(); }; -#endif // !OPENXR_ACTION_MAP_EDITOR_H +#endif // OPENXR_ACTION_MAP_EDITOR_H diff --git a/modules/openxr/editor/openxr_action_set_editor.h b/modules/openxr/editor/openxr_action_set_editor.h index f3960dcbf9..d8c85d03dd 100644 --- a/modules/openxr/editor/openxr_action_set_editor.h +++ b/modules/openxr/editor/openxr_action_set_editor.h @@ -85,4 +85,4 @@ public: OpenXRActionSetEditor(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRActionSet> p_action_set); }; -#endif // !OPENXR_ACTION_SET_EDITOR_H +#endif // OPENXR_ACTION_SET_EDITOR_H diff --git a/modules/openxr/editor/openxr_editor_plugin.h b/modules/openxr/editor/openxr_editor_plugin.h index af8ee7d54c..ce230ee95b 100644 --- a/modules/openxr/editor/openxr_editor_plugin.h +++ b/modules/openxr/editor/openxr_editor_plugin.h @@ -50,4 +50,4 @@ public: ~OpenXREditorPlugin(); }; -#endif // !OPENXR_EDITOR_PLUGIN_H +#endif // OPENXR_EDITOR_PLUGIN_H diff --git a/modules/openxr/editor/openxr_interaction_profile_editor.h b/modules/openxr/editor/openxr_interaction_profile_editor.h index f50da1a003..20a37a80eb 100644 --- a/modules/openxr/editor/openxr_interaction_profile_editor.h +++ b/modules/openxr/editor/openxr_interaction_profile_editor.h @@ -80,4 +80,4 @@ public: OpenXRInteractionProfileEditor(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile); }; -#endif // !OPENXR_INTERACTION_PROFILE_EDITOR_H +#endif // OPENXR_INTERACTION_PROFILE_EDITOR_H diff --git a/modules/openxr/editor/openxr_select_action_dialog.h b/modules/openxr/editor/openxr_select_action_dialog.h index ea2c30373b..cbe1380e18 100644 --- a/modules/openxr/editor/openxr_select_action_dialog.h +++ b/modules/openxr/editor/openxr_select_action_dialog.h @@ -64,4 +64,4 @@ public: OpenXRSelectActionDialog(Ref<OpenXRActionMap> p_action_map); }; -#endif // !OPENXR_SELECT_ACTION_DIALOG_H +#endif // OPENXR_SELECT_ACTION_DIALOG_H diff --git a/modules/openxr/editor/openxr_select_interaction_profile_dialog.h b/modules/openxr/editor/openxr_select_interaction_profile_dialog.h index d177861ff3..54bfe3120a 100644 --- a/modules/openxr/editor/openxr_select_interaction_profile_dialog.h +++ b/modules/openxr/editor/openxr_select_interaction_profile_dialog.h @@ -63,4 +63,4 @@ public: OpenXRSelectInteractionProfileDialog(); }; -#endif // !OPENXR_SELECT_INTERACTION_PROFILE_DIALOG_H +#endif // OPENXR_SELECT_INTERACTION_PROFILE_DIALOG_H diff --git a/modules/openxr/extensions/openxr_android_extension.h b/modules/openxr/extensions/openxr_android_extension.h index e102197a55..88b0e310e7 100644 --- a/modules/openxr/extensions/openxr_android_extension.h +++ b/modules/openxr/extensions/openxr_android_extension.h @@ -44,4 +44,4 @@ private: static OpenXRAndroidExtension *singleton; }; -#endif // !OPENXR_ANDROID_EXTENSION_H +#endif // OPENXR_ANDROID_EXTENSION_H diff --git a/modules/openxr/extensions/openxr_extension_wrapper.h b/modules/openxr/extensions/openxr_extension_wrapper.h index 0f7c0ba0bc..ecc6e0dd4e 100644 --- a/modules/openxr/extensions/openxr_extension_wrapper.h +++ b/modules/openxr/extensions/openxr_extension_wrapper.h @@ -32,7 +32,7 @@ #define OPENXR_EXTENSION_WRAPPER_H #include "core/error/error_macros.h" -#include "core/math/camera_matrix.h" +#include "core/math/projection.h" #include "core/templates/hash_map.h" #include "core/templates/rid.h" @@ -97,11 +97,11 @@ public: virtual String get_swapchain_format_name(int64_t p_swapchain_format) const = 0; virtual bool get_swapchain_image_data(XrSwapchain p_swapchain, int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size, void **r_swapchain_graphics_data) = 0; virtual void cleanup_swapchain_graphics_data(void **p_swapchain_graphics_data) = 0; - virtual bool create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, CameraMatrix &r_camera_matrix) = 0; + virtual bool create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, Projection &r_camera_matrix) = 0; virtual bool copy_render_target_to_image(RID p_from_render_target, void *p_swapchain_graphics_data, int p_image_index) = 0; OpenXRGraphicsExtensionWrapper(OpenXRAPI *p_openxr_api) : OpenXRExtensionWrapper(p_openxr_api){}; }; -#endif // ~OPENXR_EXTENSION_WRAPPER_H +#endif // OPENXR_EXTENSION_WRAPPER_H diff --git a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h index 7670bc074b..7f37351f27 100644 --- a/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h +++ b/modules/openxr/extensions/openxr_htc_vive_tracker_extension.h @@ -49,4 +49,4 @@ private: bool available = false; }; -#endif // !OPENXR_HTC_VIVE_TRACKER_EXTENSION_H +#endif // OPENXR_HTC_VIVE_TRACKER_EXTENSION_H diff --git a/modules/openxr/extensions/openxr_vulkan_extension.cpp b/modules/openxr/extensions/openxr_vulkan_extension.cpp index 2ddf3b8a7d..2608c4ac17 100644 --- a/modules/openxr/extensions/openxr_vulkan_extension.cpp +++ b/modules/openxr/extensions/openxr_vulkan_extension.cpp @@ -34,7 +34,6 @@ #include "../openxr_api.h" #include "../openxr_util.h" #include "servers/rendering/renderer_rd/effects/copy_effects.h" -#include "servers/rendering/renderer_rd/renderer_storage_rd.h" #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_globals.h" #include "servers/rendering_server.h" @@ -421,7 +420,7 @@ bool OpenXRVulkanExtension::get_swapchain_image_data(XrSwapchain p_swapchain, in return true; } -bool OpenXRVulkanExtension::create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, CameraMatrix &r_camera_matrix) { +bool OpenXRVulkanExtension::create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, Projection &r_camera_matrix) { // Even though this is a Vulkan renderer we're using OpenGL coordinate systems XrMatrix4x4f matrix; XrMatrix4x4f_CreateProjectionFov(&matrix, GRAPHICS_OPENGL, p_fov, (float)p_z_near, (float)p_z_far); @@ -439,7 +438,6 @@ bool OpenXRVulkanExtension::copy_render_target_to_image(RID p_from_render_target SwapchainGraphicsData *data = (SwapchainGraphicsData *)p_swapchain_graphics_data; ERR_FAIL_NULL_V(data, false); ERR_FAIL_COND_V(p_from_render_target.is_null(), false); - ERR_FAIL_NULL_V(RendererStorageRD::base_singleton, false); RID source_image = RendererRD::TextureStorage::get_singleton()->render_target_get_rd_texture(p_from_render_target); ERR_FAIL_COND_V(source_image.is_null(), false); diff --git a/modules/openxr/extensions/openxr_vulkan_extension.h b/modules/openxr/extensions/openxr_vulkan_extension.h index 1e34fe1f80..5dddc4b9c9 100644 --- a/modules/openxr/extensions/openxr_vulkan_extension.h +++ b/modules/openxr/extensions/openxr_vulkan_extension.h @@ -63,7 +63,7 @@ public: virtual String get_swapchain_format_name(int64_t p_swapchain_format) const override; virtual bool get_swapchain_image_data(XrSwapchain p_swapchain, int64_t p_swapchain_format, uint32_t p_width, uint32_t p_height, uint32_t p_sample_count, uint32_t p_array_size, void **r_swapchain_graphics_data) override; virtual void cleanup_swapchain_graphics_data(void **p_swapchain_graphics_data) override; - virtual bool create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, CameraMatrix &r_camera_matrix) override; + virtual bool create_projection_fov(const XrFovf p_fov, double p_z_near, double p_z_far, Projection &r_camera_matrix) override; virtual bool copy_render_target_to_image(RID p_from_render_target, void *p_swapchain_graphics_data, int p_image_index) override; private: @@ -90,4 +90,4 @@ private: XrResult xrCreateVulkanDeviceKHR(XrInstance p_instance, const XrVulkanDeviceCreateInfoKHR *p_create_info, VkDevice *r_device, VkResult *r_result); }; -#endif // !OPENXR_VULKAN_EXTENSION_H +#endif // OPENXR_VULKAN_EXTENSION_H diff --git a/modules/openxr/openxr_api.cpp b/modules/openxr/openxr_api.cpp index 5e35942012..92d074cb75 100644 --- a/modules/openxr/openxr_api.cpp +++ b/modules/openxr/openxr_api.cpp @@ -58,19 +58,14 @@ bool OpenXRAPI::openxr_is_enabled(bool p_check_run_in_editor) { // @TODO we need an overrule switch so we can force enable openxr, i.e run "godot --openxr_enabled" if (Engine::get_singleton()->is_editor_hint() && p_check_run_in_editor) { -#ifdef TOOLS_ENABLED // Disabled for now, using XR inside of the editor we'll be working on during the coming months. return false; - - // bool enabled = GLOBAL_GET("xr/openxr/in_editor"); // EDITOR_GET("xr/openxr/in_editor"); - // return enabled; -#else - // we should never get here, editor hint won't be true if the editor isn't compiled in. - return false; -#endif } else { - bool enabled = GLOBAL_GET("xr/openxr/enabled"); - return enabled; + if (XRServer::get_xr_mode() == XRServer::XRMODE_DEFAULT) { + return GLOBAL_GET("xr/openxr/enabled"); + } else { + return XRServer::get_xr_mode() == XRServer::XRMODE_ON; + } } } @@ -1180,7 +1175,7 @@ bool OpenXRAPI::get_view_transform(uint32_t p_view, Transform3D &r_transform) { return true; } -bool OpenXRAPI::get_view_projection(uint32_t p_view, double p_z_near, double p_z_far, CameraMatrix &p_camera_matrix) { +bool OpenXRAPI::get_view_projection(uint32_t p_view, double p_z_near, double p_z_far, Projection &p_camera_matrix) { ERR_FAIL_COND_V(!running, false); ERR_FAIL_NULL_V(graphics_extension, false); diff --git a/modules/openxr/openxr_api.h b/modules/openxr/openxr_api.h index fe9e2937b2..dc224c4237 100644 --- a/modules/openxr/openxr_api.h +++ b/modules/openxr/openxr_api.h @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef OPENXR_DRIVER_H -#define OPENXR_DRIVER_H +#ifndef OPENXR_API_H +#define OPENXR_API_H #include "core/error/error_macros.h" -#include "core/math/camera_matrix.h" +#include "core/math/projection.h" #include "core/math/transform_3d.h" #include "core/math/vector2.h" #include "core/os/memory.h" @@ -249,7 +249,7 @@ public: Size2 get_recommended_target_size(); XRPose::TrackingConfidence get_head_center(Transform3D &r_transform, Vector3 &r_linear_velocity, Vector3 &r_angular_velocity); bool get_view_transform(uint32_t p_view, Transform3D &r_transform); - bool get_view_projection(uint32_t p_view, double p_z_near, double p_z_far, CameraMatrix &p_camera_matrix); + bool get_view_projection(uint32_t p_view, double p_z_near, double p_z_far, Projection &p_camera_matrix); bool process(); void pre_render(); @@ -292,4 +292,4 @@ public: ~OpenXRAPI(); }; -#endif // !OPENXR_DRIVER_H +#endif // OPENXR_API_H diff --git a/modules/openxr/openxr_interface.cpp b/modules/openxr/openxr_interface.cpp index 9dfa005600..1447be5c77 100644 --- a/modules/openxr/openxr_interface.cpp +++ b/modules/openxr/openxr_interface.cpp @@ -631,8 +631,8 @@ Transform3D OpenXRInterface::get_transform_for_view(uint32_t p_view, const Trans return p_cam_transform * xr_server->get_reference_frame() * t; } -CameraMatrix OpenXRInterface::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) { - CameraMatrix cm; +Projection OpenXRInterface::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) { + Projection cm; if (openxr_api) { if (openxr_api->get_view_projection(p_view, p_z_near, p_z_far, cm)) { diff --git a/modules/openxr/openxr_interface.h b/modules/openxr/openxr_interface.h index a223acfed0..a99012fd1d 100644 --- a/modules/openxr/openxr_interface.h +++ b/modules/openxr/openxr_interface.h @@ -121,7 +121,7 @@ public: virtual uint32_t get_view_count() override; virtual Transform3D get_camera_transform() override; virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override; - virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override; + virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override; virtual void process() override; virtual void pre_render() override; @@ -140,4 +140,4 @@ public: ~OpenXRInterface(); }; -#endif // !OPENXR_INTERFACE_H +#endif // OPENXR_INTERFACE_H diff --git a/modules/openxr/openxr_util.h b/modules/openxr/openxr_util.h index 4371b74d2f..a5cc7cd512 100644 --- a/modules/openxr/openxr_util.h +++ b/modules/openxr/openxr_util.h @@ -44,4 +44,4 @@ public: static String make_xr_version_string(XrVersion p_version); }; -#endif // !OPENXR_UTIL_H +#endif // OPENXR_UTIL_H diff --git a/modules/raycast/lightmap_raycaster.h b/modules/raycast/lightmap_raycaster.h index 4266b46ea8..2e9f59dda4 100644 --- a/modules/raycast/lightmap_raycaster.h +++ b/modules/raycast/lightmap_raycaster.h @@ -74,4 +74,4 @@ public: ~LightmapRaycasterEmbree(); }; -#endif +#endif // LIGHTMAP_RAYCASTER_H diff --git a/modules/raycast/raycast_occlusion_cull.cpp b/modules/raycast/raycast_occlusion_cull.cpp index 89e75f774e..13824c3830 100644 --- a/modules/raycast/raycast_occlusion_cull.cpp +++ b/modules/raycast/raycast_occlusion_cull.cpp @@ -30,6 +30,7 @@ #include "raycast_occlusion_cull.h" #include "core/config/project_settings.h" +#include "core/object/worker_thread_pool.h" #include "core/templates/local_vector.h" #ifdef __SSE2__ @@ -78,9 +79,9 @@ void RaycastOcclusionCull::RaycastHZBuffer::resize(const Size2i &p_size) { memset(camera_ray_masks.ptr(), ~0, camera_rays_tile_count * TILE_RAYS * sizeof(uint32_t)); } -void RaycastOcclusionCull::RaycastHZBuffer::update_camera_rays(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_work_pool) { +void RaycastOcclusionCull::RaycastHZBuffer::update_camera_rays(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal) { CameraRayThreadData td; - td.thread_count = p_thread_work_pool.get_thread_count(); + td.thread_count = WorkerThreadPool::get_singleton()->get_thread_count(); td.z_near = p_cam_projection.get_z_near(); td.z_far = p_cam_projection.get_z_far() * 1.05f; @@ -88,7 +89,7 @@ void RaycastOcclusionCull::RaycastHZBuffer::update_camera_rays(const Transform3D td.camera_dir = -p_cam_transform.basis.get_column(2); td.camera_orthogonal = p_cam_orthogonal; - CameraMatrix inv_camera_matrix = p_cam_projection.inverse(); + Projection inv_camera_matrix = p_cam_projection.inverse(); Vector3 camera_corner_proj = Vector3(-1.0f, -1.0f, -1.0f); Vector3 camera_corner_view = inv_camera_matrix.xform(camera_corner_proj); td.pixel_corner = p_cam_transform.xform(camera_corner_view); @@ -106,7 +107,8 @@ void RaycastOcclusionCull::RaycastHZBuffer::update_camera_rays(const Transform3D debug_tex_range = td.z_far; - p_thread_work_pool.do_work(td.thread_count, this, &RaycastHZBuffer::_camera_rays_threaded, &td); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RaycastHZBuffer::_camera_rays_threaded, &td, td.thread_count, -1, true, SNAME("RaycastOcclusionCullUpdateCamera")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); } void RaycastOcclusionCull::RaycastHZBuffer::_camera_rays_threaded(uint32_t p_thread, const CameraRayThreadData *p_data) { @@ -331,10 +333,10 @@ void RaycastOcclusionCull::scenario_remove_instance(RID p_scenario, RID p_instan } void RaycastOcclusionCull::Scenario::_update_dirty_instance_thread(int p_idx, RID *p_instances) { - _update_dirty_instance(p_idx, p_instances, nullptr); + _update_dirty_instance(p_idx, p_instances); } -void RaycastOcclusionCull::Scenario::_update_dirty_instance(int p_idx, RID *p_instances, ThreadWorkPool *p_thread_pool) { +void RaycastOcclusionCull::Scenario::_update_dirty_instance(int p_idx, RID *p_instances) { OccluderInstance *occ_inst = instances.getptr(p_instances[p_idx]); if (!occ_inst) { @@ -355,14 +357,16 @@ void RaycastOcclusionCull::Scenario::_update_dirty_instance(int p_idx, RID *p_in const Vector3 *read_ptr = occ->vertices.ptr(); Vector3 *write_ptr = occ_inst->xformed_vertices.ptr(); - if (p_thread_pool && vertices_size > 1024) { + if (vertices_size > 1024) { TransformThreadData td; td.xform = occ_inst->xform; td.read = read_ptr; td.write = write_ptr; td.vertex_count = vertices_size; - td.thread_count = p_thread_pool->get_thread_count(); - p_thread_pool->do_work(td.thread_count, this, &Scenario::_transform_vertices_thread, &td); + td.thread_count = WorkerThreadPool::get_singleton()->get_thread_count(); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &Scenario::_transform_vertices_thread, &td, td.thread_count, -1, true, SNAME("RaycastOcclusionCull")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); + } else { _transform_vertices_range(read_ptr, write_ptr, occ_inst->xform, 0, vertices_size); } @@ -392,7 +396,7 @@ void RaycastOcclusionCull::Scenario::_commit_scene(void *p_ud) { scenario->commit_done = true; } -bool RaycastOcclusionCull::Scenario::update(ThreadWorkPool &p_thread_pool) { +bool RaycastOcclusionCull::Scenario::update() { ERR_FAIL_COND_V(singleton == nullptr, false); if (commit_thread == nullptr) { @@ -426,13 +430,15 @@ bool RaycastOcclusionCull::Scenario::update(ThreadWorkPool &p_thread_pool) { instances.erase(removed_instances[i]); } - if (dirty_instances_array.size() / p_thread_pool.get_thread_count() > 128) { + if (dirty_instances_array.size() / WorkerThreadPool::get_singleton()->get_thread_count() > 128) { // Lots of instances, use per-instance threading - p_thread_pool.do_work(dirty_instances_array.size(), this, &Scenario::_update_dirty_instance_thread, dirty_instances_array.ptr()); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &Scenario::_update_dirty_instance_thread, dirty_instances_array.ptr(), dirty_instances_array.size(), -1, true, SNAME("RaycastOcclusionCullUpdate")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); + } else { // Few instances, use threading on the vertex transforms for (unsigned int i = 0; i < dirty_instances_array.size(); i++) { - _update_dirty_instance(i, dirty_instances_array.ptr(), &p_thread_pool); + _update_dirty_instance(i, dirty_instances_array.ptr()); } } @@ -484,7 +490,7 @@ void RaycastOcclusionCull::Scenario::_raycast(uint32_t p_idx, const RaycastThrea rtcIntersect16((const int *)&p_raycast_data->masks[p_idx * TILE_RAYS], ebr_scene[current_scene_idx], &ctx, &p_raycast_data->rays[p_idx]); } -void RaycastOcclusionCull::Scenario::raycast(CameraRayTile *r_rays, const uint32_t *p_valid_masks, uint32_t p_tile_count, ThreadWorkPool &p_thread_pool) const { +void RaycastOcclusionCull::Scenario::raycast(CameraRayTile *r_rays, const uint32_t *p_valid_masks, uint32_t p_tile_count) const { ERR_FAIL_COND(singleton == nullptr); if (raycast_singleton->ebr_device == nullptr) { return; // Embree is initialized on demand when there is some scenario with occluders in it. @@ -498,7 +504,8 @@ void RaycastOcclusionCull::Scenario::raycast(CameraRayTile *r_rays, const uint32 td.rays = r_rays; td.masks = p_valid_masks; - p_thread_pool.do_work(p_tile_count, this, &Scenario::_raycast, &td); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &Scenario::_raycast, &td, p_tile_count, -1, true, SNAME("RaycastOcclusionCullRaycast")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); } //////////////////////////////////////////////////////// @@ -524,7 +531,7 @@ void RaycastOcclusionCull::buffer_set_size(RID p_buffer, const Vector2i &p_size) buffers[p_buffer].resize(p_size); } -void RaycastOcclusionCull::buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_pool) { +void RaycastOcclusionCull::buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal) { if (!buffers.has(p_buffer)) { return; } @@ -537,16 +544,16 @@ void RaycastOcclusionCull::buffer_update(RID p_buffer, const Transform3D &p_cam_ Scenario &scenario = scenarios[buffer.scenario_rid]; - bool removed = scenario.update(p_thread_pool); + bool removed = scenario.update(); if (removed) { scenarios.erase(buffer.scenario_rid); return; } - buffer.update_camera_rays(p_cam_transform, p_cam_projection, p_cam_orthogonal, p_thread_pool); + buffer.update_camera_rays(p_cam_transform, p_cam_projection, p_cam_orthogonal); - scenario.raycast(buffer.camera_rays, buffer.camera_ray_masks.ptr(), buffer.camera_rays_tile_count, p_thread_pool); + scenario.raycast(buffer.camera_rays, buffer.camera_ray_masks.ptr(), buffer.camera_rays_tile_count); buffer.sort_rays(-p_cam_transform.basis.get_column(2), p_cam_orthogonal); buffer.update_mips(); } diff --git a/modules/raycast/raycast_occlusion_cull.h b/modules/raycast/raycast_occlusion_cull.h index 6562c4e9c4..056b808640 100644 --- a/modules/raycast/raycast_occlusion_cull.h +++ b/modules/raycast/raycast_occlusion_cull.h @@ -28,11 +28,11 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef OCCLUSION_CULL_RAYCASTER_H -#define OCCLUSION_CULL_RAYCASTER_H +#ifndef RAYCAST_OCCLUSION_CULL_H +#define RAYCAST_OCCLUSION_CULL_H #include "core/io/image.h" -#include "core/math/camera_matrix.h" +#include "core/math/projection.h" #include "core/object/object.h" #include "core/object/ref_counted.h" #include "core/templates/local_vector.h" @@ -76,7 +76,7 @@ public: virtual void clear() override; virtual void resize(const Size2i &p_size) override; void sort_rays(const Vector3 &p_camera_dir, bool p_orthogonal); - void update_camera_rays(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_work_pool); + void update_camera_rays(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal); ~RaycastHZBuffer(); }; @@ -143,14 +143,14 @@ private: LocalVector<RID> removed_instances; void _update_dirty_instance_thread(int p_idx, RID *p_instances); - void _update_dirty_instance(int p_idx, RID *p_instances, ThreadWorkPool *p_thread_pool); + void _update_dirty_instance(int p_idx, RID *p_instances); void _transform_vertices_thread(uint32_t p_thread, TransformThreadData *p_data); void _transform_vertices_range(const Vector3 *p_read, Vector3 *p_write, const Transform3D &p_xform, int p_from, int p_to); static void _commit_scene(void *p_ud); - bool update(ThreadWorkPool &p_thread_pool); + bool update(); void _raycast(uint32_t p_thread, const RaycastThreadData *p_raycast_data) const; - void raycast(CameraRayTile *r_rays, const uint32_t *p_valid_masks, uint32_t p_tile_count, ThreadWorkPool &p_thread_pool) const; + void raycast(CameraRayTile *r_rays, const uint32_t *p_valid_masks, uint32_t p_tile_count) const; }; static RaycastOcclusionCull *raycast_singleton; @@ -183,7 +183,8 @@ public: virtual HZBuffer *buffer_get_ptr(RID p_buffer) override; virtual void buffer_set_scenario(RID p_buffer, RID p_scenario) override; virtual void buffer_set_size(RID p_buffer, const Vector2i &p_size) override; - virtual void buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_pool) override; + virtual void buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal) override; + virtual RID buffer_get_debug_texture(RID p_buffer) override; virtual void set_build_quality(RS::ViewportOcclusionCullingBuildQuality p_quality) override; @@ -192,4 +193,4 @@ public: ~RaycastOcclusionCull(); }; -#endif // OCCLUSION_CULL_RAYCASTER_H +#endif // RAYCAST_OCCLUSION_CULL_H diff --git a/modules/raycast/static_raycaster.h b/modules/raycast/static_raycaster.h index e2909f9b56..607a392683 100644 --- a/modules/raycast/static_raycaster.h +++ b/modules/raycast/static_raycaster.h @@ -61,4 +61,4 @@ public: ~StaticRaycasterEmbree(); }; -#endif +#endif // STATIC_RAYCASTER_H diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp index dcb1f1d744..87e2fae2d0 100644 --- a/modules/svg/image_loader_svg.cpp +++ b/modules/svg/image_loader_svg.cpp @@ -80,8 +80,8 @@ void ImageLoaderSVG::create_image_from_string(Ref<Image> p_image, String p_strin float fw, fh; picture->size(&fw, &fh); - uint32_t width = MIN(fw * p_scale, 16 * 1024); - uint32_t height = MIN(fh * p_scale, 16 * 1024); + uint32_t width = MIN(round(fw * p_scale), 16 * 1024); + uint32_t height = MIN(round(fh * p_scale), 16 * 1024); picture->size(width, height); std::unique_ptr<tvg::SwCanvas> sw_canvas = tvg::SwCanvas::gen(); diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub index a46f17311a..2d764a4006 100644 --- a/modules/text_server_adv/SCsub +++ b/modules/text_server_adv/SCsub @@ -75,18 +75,18 @@ if env["builtin_harfbuzz"]: "src/hb-ot-meta.cc", "src/hb-ot-metrics.cc", "src/hb-ot-name.cc", - "src/hb-ot-shape-complex-arabic.cc", - "src/hb-ot-shape-complex-default.cc", - "src/hb-ot-shape-complex-hangul.cc", - "src/hb-ot-shape-complex-hebrew.cc", - "src/hb-ot-shape-complex-indic-table.cc", - "src/hb-ot-shape-complex-indic.cc", - "src/hb-ot-shape-complex-khmer.cc", - "src/hb-ot-shape-complex-myanmar.cc", - "src/hb-ot-shape-complex-syllabic.cc", - "src/hb-ot-shape-complex-thai.cc", - "src/hb-ot-shape-complex-use.cc", - "src/hb-ot-shape-complex-vowel-constraints.cc", + "src/hb-ot-shaper-arabic.cc", + "src/hb-ot-shaper-default.cc", + "src/hb-ot-shaper-hangul.cc", + "src/hb-ot-shaper-hebrew.cc", + "src/hb-ot-shaper-indic-table.cc", + "src/hb-ot-shaper-indic.cc", + "src/hb-ot-shaper-khmer.cc", + "src/hb-ot-shaper-myanmar.cc", + "src/hb-ot-shaper-syllabic.cc", + "src/hb-ot-shaper-thai.cc", + "src/hb-ot-shaper-use.cc", + "src/hb-ot-shaper-vowel-constraints.cc", "src/hb-ot-shape-fallback.cc", "src/hb-ot-shape-normalize.cc", "src/hb-ot-shape.cc", diff --git a/modules/text_server_adv/gdextension_build/SConstruct b/modules/text_server_adv/gdextension_build/SConstruct index 0e36ef6805..0170c007ae 100644 --- a/modules/text_server_adv/gdextension_build/SConstruct +++ b/modules/text_server_adv/gdextension_build/SConstruct @@ -220,18 +220,18 @@ thirdparty_harfbuzz_sources = [ "src/hb-ot-meta.cc", "src/hb-ot-metrics.cc", "src/hb-ot-name.cc", - "src/hb-ot-shape-complex-arabic.cc", - "src/hb-ot-shape-complex-default.cc", - "src/hb-ot-shape-complex-hangul.cc", - "src/hb-ot-shape-complex-hebrew.cc", - "src/hb-ot-shape-complex-indic-table.cc", - "src/hb-ot-shape-complex-indic.cc", - "src/hb-ot-shape-complex-khmer.cc", - "src/hb-ot-shape-complex-myanmar.cc", - "src/hb-ot-shape-complex-syllabic.cc", - "src/hb-ot-shape-complex-thai.cc", - "src/hb-ot-shape-complex-use.cc", - "src/hb-ot-shape-complex-vowel-constraints.cc", + "src/hb-ot-shaper-arabic.cc", + "src/hb-ot-shaper-default.cc", + "src/hb-ot-shaper-hangul.cc", + "src/hb-ot-shaper-hebrew.cc", + "src/hb-ot-shaper-indic-table.cc", + "src/hb-ot-shaper-indic.cc", + "src/hb-ot-shaper-khmer.cc", + "src/hb-ot-shaper-myanmar.cc", + "src/hb-ot-shaper-syllabic.cc", + "src/hb-ot-shaper-thai.cc", + "src/hb-ot-shaper-use.cc", + "src/hb-ot-shaper-vowel-constraints.cc", "src/hb-ot-shape-fallback.cc", "src/hb-ot-shape-normalize.cc", "src/hb-ot-shape.cc", @@ -624,15 +624,15 @@ env.Append(CPPDEFINES=["GDEXTENSION"]) env.Append(CPPPATH=["../"]) sources = Glob("../*.cpp") -if env["platform"] == "osx": - methods.write_osx_plist( - f'./bin/libtextserver_advanced.osx.{env["target"]}.framework', - f'libtextserver_advanced.osx.{env["target"]}', +if env["platform"] == "macos": + methods.write_macos_plist( + f'./bin/libtextserver_advanced.macos.{env["target"]}.framework', + f'libtextserver_advanced.macos.{env["target"]}', "org.godotengine.textserver_advanced", "ICU / HarfBuzz / Graphite Text Server", ) library = env.SharedLibrary( - f'./bin/libtextserver_advanced.osx.{env["target"]}.framework/libtextserver_advanced.osx.{env["target"]}', + f'./bin/libtextserver_advanced.macos.{env["target"]}.framework/libtextserver_advanced.macos.{env["target"]}', source=sources, ) else: diff --git a/modules/text_server_adv/gdextension_build/methods.py b/modules/text_server_adv/gdextension_build/methods.py index d404f2851e..3c5229462c 100644 --- a/modules/text_server_adv/gdextension_build/methods.py +++ b/modules/text_server_adv/gdextension_build/methods.py @@ -98,7 +98,7 @@ def make_icu_data(target, source, env): g.write("#endif") -def write_osx_plist(target, binary_name, identifier, name): +def write_macos_plist(target, binary_name, identifier, name): os.makedirs(f"{target}/Resourece/", exist_ok=True) f = open(f"{target}/Resourece/Info.plist", "w") diff --git a/modules/text_server_adv/gdextension_build/text_server_adv.gdextension b/modules/text_server_adv/gdextension_build/text_server_adv.gdextension index 5956476a5e..11ed271ae9 100644 --- a/modules/text_server_adv/gdextension_build/text_server_adv.gdextension +++ b/modules/text_server_adv/gdextension_build/text_server_adv.gdextension @@ -8,5 +8,5 @@ linux.64.debug = "bin/libtextserver_advanced.linux.debug.64.so" linux.64.release = "bin/libtextserver_advanced.linux.release.64.so" windows.64.debug = "bin/libtextserver_advanced.windows.debug.64.dll" windows.64.release = "bin/libtextserver_advanced.windows.release.64.dll" -macos.debug = "bin/libtextserver_advanced.osx.debug.framework" -macos.release = "bin/libtextserver_advanced.osx.release.framework" +macos.debug = "bin/libtextserver_advanced.macos.debug.framework" +macos.release = "bin/libtextserver_advanced.macos.release.framework" diff --git a/modules/text_server_adv/script_iterator.h b/modules/text_server_adv/script_iterator.h index 2bd045b91a..025b62c6fb 100644 --- a/modules/text_server_adv/script_iterator.h +++ b/modules/text_server_adv/script_iterator.h @@ -75,4 +75,4 @@ public: ScriptIterator(const String &p_string, int p_start, int p_length); }; -#endif //SCRIPT_ITERATOR_H +#endif // SCRIPT_ITERATOR_H diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index c4269a53f4..fa234081f0 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "text_server_adv.h" +#include "core/object/worker_thread_pool.h" #ifdef GDEXTENSION // Headers for building as GDExtension plug-in. @@ -75,7 +76,7 @@ using namespace core_bind; hb_font_funcs_t *TextServerAdvanced::funcs = nullptr; -TextServerAdvanced::bmp_font_t *TextServerAdvanced::_bmp_font_create(TextServerAdvanced::FontDataForSizeAdvanced *p_face, bool p_unref) { +TextServerAdvanced::bmp_font_t *TextServerAdvanced::_bmp_font_create(TextServerAdvanced::FontForSizeAdvanced *p_face, bool p_unref) { bmp_font_t *bm_font = memnew(bmp_font_t); if (!bm_font) { @@ -228,11 +229,11 @@ void TextServerAdvanced::_bmp_free_font_funcs() { } } -void TextServerAdvanced::_bmp_font_set_funcs(hb_font_t *p_font, TextServerAdvanced::FontDataForSizeAdvanced *p_face, bool p_unref) { +void TextServerAdvanced::_bmp_font_set_funcs(hb_font_t *p_font, TextServerAdvanced::FontForSizeAdvanced *p_face, bool p_unref) { hb_font_set_funcs(p_font, funcs, _bmp_font_create(p_face, p_unref), _bmp_font_destroy); } -hb_font_t *TextServerAdvanced::_bmp_font_create(TextServerAdvanced::FontDataForSizeAdvanced *p_face, hb_destroy_func_t p_destroy) { +hb_font_t *TextServerAdvanced::_bmp_font_create(TextServerAdvanced::FontForSizeAdvanced *p_face, hb_destroy_func_t p_destroy) { hb_font_t *font; hb_face_t *face = hb_face_create(nullptr, 0); @@ -375,7 +376,7 @@ int64_t TextServerAdvanced::get_features() const { void TextServerAdvanced::free_rid(const RID &p_rid) { _THREAD_SAFE_METHOD_ if (font_owner.owns(p_rid)) { - FontDataAdvanced *fd = font_owner.get_or_null(p_rid); + FontAdvanced *fd = font_owner.get_or_null(p_rid); font_owner.free(p_rid); memdelete(fd); } else if (shaped_owner.owns(p_rid)) { @@ -476,259 +477,267 @@ bool TextServerAdvanced::is_locale_right_to_left(const String &p_locale) const { } } -_FORCE_INLINE_ void TextServerAdvanced::_insert_feature(const StringName &p_name, int32_t p_tag) { +_FORCE_INLINE_ void TextServerAdvanced::_insert_feature(const StringName &p_name, int32_t p_tag, Variant::Type p_vtype, bool p_hidden) { + FeatureInfo fi; + fi.name = p_name; + fi.vtype = p_vtype; + fi.hidden = p_hidden; + feature_sets.insert(p_name, p_tag); - feature_sets_inv.insert(p_tag, p_name); + feature_sets_inv.insert(p_tag, fi); } void TextServerAdvanced::_insert_feature_sets() { // Registered OpenType feature tags. - _insert_feature("access_all_alternates", HB_TAG('a', 'a', 'l', 't')); - _insert_feature("above_base_forms", HB_TAG('a', 'b', 'v', 'f')); - _insert_feature("above_base_mark_positioning", HB_TAG('a', 'b', 'v', 'm')); - _insert_feature("above_base_substitutions", HB_TAG('a', 'b', 'v', 's')); - _insert_feature("alternative_fractions", HB_TAG('a', 'f', 'r', 'c')); - _insert_feature("akhands", HB_TAG('a', 'k', 'h', 'n')); - _insert_feature("below_base_forms", HB_TAG('b', 'l', 'w', 'f')); - _insert_feature("below_base_mark_positioning", HB_TAG('b', 'l', 'w', 'm')); - _insert_feature("below_base_substitutions", HB_TAG('b', 'l', 'w', 's')); - _insert_feature("contextual_alternates", HB_TAG('c', 'a', 'l', 't')); - _insert_feature("case_sensitive_forms", HB_TAG('c', 'a', 's', 'e')); - _insert_feature("glyph_composition", HB_TAG('c', 'c', 'm', 'p')); - _insert_feature("conjunct_form_after_ro", HB_TAG('c', 'f', 'a', 'r')); - _insert_feature("conjunct_forms", HB_TAG('c', 'j', 'c', 't')); - _insert_feature("contextual_ligatures", HB_TAG('c', 'l', 'i', 'g')); - _insert_feature("centered_cjk_punctuation", HB_TAG('c', 'p', 'c', 't')); - _insert_feature("capital_spacing", HB_TAG('c', 'p', 's', 'p')); - _insert_feature("contextual_swash", HB_TAG('c', 's', 'w', 'h')); - _insert_feature("cursive_positioning", HB_TAG('c', 'u', 'r', 's')); - _insert_feature("character_variant_01", HB_TAG('c', 'v', '0', '1')); - _insert_feature("character_variant_02", HB_TAG('c', 'v', '0', '2')); - _insert_feature("character_variant_03", HB_TAG('c', 'v', '0', '3')); - _insert_feature("character_variant_04", HB_TAG('c', 'v', '0', '4')); - _insert_feature("character_variant_05", HB_TAG('c', 'v', '0', '5')); - _insert_feature("character_variant_06", HB_TAG('c', 'v', '0', '6')); - _insert_feature("character_variant_07", HB_TAG('c', 'v', '0', '7')); - _insert_feature("character_variant_08", HB_TAG('c', 'v', '0', '8')); - _insert_feature("character_variant_09", HB_TAG('c', 'v', '0', '9')); - _insert_feature("character_variant_10", HB_TAG('c', 'v', '1', '0')); - _insert_feature("character_variant_11", HB_TAG('c', 'v', '1', '1')); - _insert_feature("character_variant_12", HB_TAG('c', 'v', '1', '2')); - _insert_feature("character_variant_13", HB_TAG('c', 'v', '1', '3')); - _insert_feature("character_variant_14", HB_TAG('c', 'v', '1', '4')); - _insert_feature("character_variant_15", HB_TAG('c', 'v', '1', '5')); - _insert_feature("character_variant_16", HB_TAG('c', 'v', '1', '6')); - _insert_feature("character_variant_17", HB_TAG('c', 'v', '1', '7')); - _insert_feature("character_variant_18", HB_TAG('c', 'v', '1', '8')); - _insert_feature("character_variant_19", HB_TAG('c', 'v', '1', '9')); - _insert_feature("character_variant_20", HB_TAG('c', 'v', '2', '0')); - _insert_feature("character_variant_21", HB_TAG('c', 'v', '2', '1')); - _insert_feature("character_variant_22", HB_TAG('c', 'v', '2', '2')); - _insert_feature("character_variant_23", HB_TAG('c', 'v', '2', '3')); - _insert_feature("character_variant_24", HB_TAG('c', 'v', '2', '4')); - _insert_feature("character_variant_25", HB_TAG('c', 'v', '2', '5')); - _insert_feature("character_variant_26", HB_TAG('c', 'v', '2', '6')); - _insert_feature("character_variant_27", HB_TAG('c', 'v', '2', '7')); - _insert_feature("character_variant_28", HB_TAG('c', 'v', '2', '8')); - _insert_feature("character_variant_29", HB_TAG('c', 'v', '2', '9')); - _insert_feature("character_variant_30", HB_TAG('c', 'v', '3', '0')); - _insert_feature("character_variant_31", HB_TAG('c', 'v', '3', '1')); - _insert_feature("character_variant_32", HB_TAG('c', 'v', '3', '2')); - _insert_feature("character_variant_33", HB_TAG('c', 'v', '3', '3')); - _insert_feature("character_variant_34", HB_TAG('c', 'v', '3', '4')); - _insert_feature("character_variant_35", HB_TAG('c', 'v', '3', '5')); - _insert_feature("character_variant_36", HB_TAG('c', 'v', '3', '6')); - _insert_feature("character_variant_37", HB_TAG('c', 'v', '3', '7')); - _insert_feature("character_variant_38", HB_TAG('c', 'v', '3', '8')); - _insert_feature("character_variant_39", HB_TAG('c', 'v', '3', '9')); - _insert_feature("character_variant_40", HB_TAG('c', 'v', '4', '0')); - _insert_feature("character_variant_41", HB_TAG('c', 'v', '4', '1')); - _insert_feature("character_variant_42", HB_TAG('c', 'v', '4', '2')); - _insert_feature("character_variant_43", HB_TAG('c', 'v', '4', '3')); - _insert_feature("character_variant_44", HB_TAG('c', 'v', '4', '4')); - _insert_feature("character_variant_45", HB_TAG('c', 'v', '4', '5')); - _insert_feature("character_variant_46", HB_TAG('c', 'v', '4', '6')); - _insert_feature("character_variant_47", HB_TAG('c', 'v', '4', '7')); - _insert_feature("character_variant_48", HB_TAG('c', 'v', '4', '8')); - _insert_feature("character_variant_49", HB_TAG('c', 'v', '4', '9')); - _insert_feature("character_variant_50", HB_TAG('c', 'v', '5', '0')); - _insert_feature("character_variant_51", HB_TAG('c', 'v', '5', '1')); - _insert_feature("character_variant_52", HB_TAG('c', 'v', '5', '2')); - _insert_feature("character_variant_53", HB_TAG('c', 'v', '5', '3')); - _insert_feature("character_variant_54", HB_TAG('c', 'v', '5', '4')); - _insert_feature("character_variant_55", HB_TAG('c', 'v', '5', '5')); - _insert_feature("character_variant_56", HB_TAG('c', 'v', '5', '6')); - _insert_feature("character_variant_57", HB_TAG('c', 'v', '5', '7')); - _insert_feature("character_variant_58", HB_TAG('c', 'v', '5', '8')); - _insert_feature("character_variant_59", HB_TAG('c', 'v', '5', '9')); - _insert_feature("character_variant_60", HB_TAG('c', 'v', '6', '0')); - _insert_feature("character_variant_61", HB_TAG('c', 'v', '6', '1')); - _insert_feature("character_variant_62", HB_TAG('c', 'v', '6', '2')); - _insert_feature("character_variant_63", HB_TAG('c', 'v', '6', '3')); - _insert_feature("character_variant_64", HB_TAG('c', 'v', '6', '4')); - _insert_feature("character_variant_65", HB_TAG('c', 'v', '6', '5')); - _insert_feature("character_variant_66", HB_TAG('c', 'v', '6', '6')); - _insert_feature("character_variant_67", HB_TAG('c', 'v', '6', '7')); - _insert_feature("character_variant_68", HB_TAG('c', 'v', '6', '8')); - _insert_feature("character_variant_69", HB_TAG('c', 'v', '6', '9')); - _insert_feature("character_variant_70", HB_TAG('c', 'v', '7', '0')); - _insert_feature("character_variant_71", HB_TAG('c', 'v', '7', '1')); - _insert_feature("character_variant_72", HB_TAG('c', 'v', '7', '2')); - _insert_feature("character_variant_73", HB_TAG('c', 'v', '7', '3')); - _insert_feature("character_variant_74", HB_TAG('c', 'v', '7', '4')); - _insert_feature("character_variant_75", HB_TAG('c', 'v', '7', '5')); - _insert_feature("character_variant_76", HB_TAG('c', 'v', '7', '6')); - _insert_feature("character_variant_77", HB_TAG('c', 'v', '7', '7')); - _insert_feature("character_variant_78", HB_TAG('c', 'v', '7', '8')); - _insert_feature("character_variant_79", HB_TAG('c', 'v', '7', '9')); - _insert_feature("character_variant_80", HB_TAG('c', 'v', '8', '0')); - _insert_feature("character_variant_81", HB_TAG('c', 'v', '8', '1')); - _insert_feature("character_variant_82", HB_TAG('c', 'v', '8', '2')); - _insert_feature("character_variant_83", HB_TAG('c', 'v', '8', '3')); - _insert_feature("character_variant_84", HB_TAG('c', 'v', '8', '4')); - _insert_feature("character_variant_85", HB_TAG('c', 'v', '8', '5')); - _insert_feature("character_variant_86", HB_TAG('c', 'v', '8', '6')); - _insert_feature("character_variant_87", HB_TAG('c', 'v', '8', '7')); - _insert_feature("character_variant_88", HB_TAG('c', 'v', '8', '8')); - _insert_feature("character_variant_89", HB_TAG('c', 'v', '8', '9')); - _insert_feature("character_variant_90", HB_TAG('c', 'v', '9', '0')); - _insert_feature("character_variant_91", HB_TAG('c', 'v', '9', '1')); - _insert_feature("character_variant_92", HB_TAG('c', 'v', '9', '2')); - _insert_feature("character_variant_93", HB_TAG('c', 'v', '9', '3')); - _insert_feature("character_variant_94", HB_TAG('c', 'v', '9', '4')); - _insert_feature("character_variant_95", HB_TAG('c', 'v', '9', '5')); - _insert_feature("character_variant_96", HB_TAG('c', 'v', '9', '6')); - _insert_feature("character_variant_97", HB_TAG('c', 'v', '9', '7')); - _insert_feature("character_variant_98", HB_TAG('c', 'v', '9', '8')); - _insert_feature("character_variant_99", HB_TAG('c', 'v', '9', '9')); - _insert_feature("petite_capitals_from_capitals", HB_TAG('c', '2', 'p', 'c')); - _insert_feature("small_capitals_from_capitals", HB_TAG('c', '2', 's', 'c')); - _insert_feature("distances", HB_TAG('d', 'i', 's', 't')); - _insert_feature("discretionary_ligatures", HB_TAG('d', 'l', 'i', 'g')); - _insert_feature("denominators", HB_TAG('d', 'n', 'o', 'm')); - _insert_feature("dotless_forms", HB_TAG('d', 't', 'l', 's')); - _insert_feature("expert_forms", HB_TAG('e', 'x', 'p', 't')); - _insert_feature("final_glyph_on_line_alternates", HB_TAG('f', 'a', 'l', 't')); - _insert_feature("terminal_forms_2", HB_TAG('f', 'i', 'n', '2')); - _insert_feature("terminal_forms_3", HB_TAG('f', 'i', 'n', '3')); - _insert_feature("terminal_forms", HB_TAG('f', 'i', 'n', 'a')); - _insert_feature("flattened_accent_forms", HB_TAG('f', 'l', 'a', 'c')); - _insert_feature("fractions", HB_TAG('f', 'r', 'a', 'c')); - _insert_feature("full_widths", HB_TAG('f', 'w', 'i', 'd')); - _insert_feature("half_forms", HB_TAG('h', 'a', 'l', 'f')); - _insert_feature("halant_forms", HB_TAG('h', 'a', 'l', 'n')); - _insert_feature("alternate_half_widths", HB_TAG('h', 'a', 'l', 't')); - _insert_feature("historical_forms", HB_TAG('h', 'i', 's', 't')); - _insert_feature("horizontal_kana_alternates", HB_TAG('h', 'k', 'n', 'a')); - _insert_feature("historical_ligatures", HB_TAG('h', 'l', 'i', 'g')); - _insert_feature("hangul", HB_TAG('h', 'n', 'g', 'l')); - _insert_feature("hojo_kanji_forms", HB_TAG('h', 'o', 'j', 'o')); - _insert_feature("half_widths", HB_TAG('h', 'w', 'i', 'd')); - _insert_feature("initial_forms", HB_TAG('i', 'n', 'i', 't')); - _insert_feature("isolated_forms", HB_TAG('i', 's', 'o', 'l')); - _insert_feature("italics", HB_TAG('i', 't', 'a', 'l')); - _insert_feature("justification_alternates", HB_TAG('j', 'a', 'l', 't')); - _insert_feature("jis78_forms", HB_TAG('j', 'p', '7', '8')); - _insert_feature("jis83_forms", HB_TAG('j', 'p', '8', '3')); - _insert_feature("jis90_forms", HB_TAG('j', 'p', '9', '0')); - _insert_feature("jis2004_forms", HB_TAG('j', 'p', '0', '4')); - _insert_feature("kerning", HB_TAG('k', 'e', 'r', 'n')); - _insert_feature("left_bounds", HB_TAG('l', 'f', 'b', 'd')); - _insert_feature("standard_ligatures", HB_TAG('l', 'i', 'g', 'a')); - _insert_feature("leading_jamo_forms", HB_TAG('l', 'j', 'm', 'o')); - _insert_feature("lining_figures", HB_TAG('l', 'n', 'u', 'm')); - _insert_feature("localized_forms", HB_TAG('l', 'o', 'c', 'l')); - _insert_feature("left_to_right_alternates", HB_TAG('l', 't', 'r', 'a')); - _insert_feature("left_to_right_mirrored_forms", HB_TAG('l', 't', 'r', 'm')); - _insert_feature("mark_positioning", HB_TAG('m', 'a', 'r', 'k')); - _insert_feature("medial_forms_2", HB_TAG('m', 'e', 'd', '2')); - _insert_feature("medial_forms", HB_TAG('m', 'e', 'd', 'i')); - _insert_feature("mathematical_greek", HB_TAG('m', 'g', 'r', 'k')); - _insert_feature("mark_to_mark_positioning", HB_TAG('m', 'k', 'm', 'k')); - _insert_feature("mark_positioning_via_substitution", HB_TAG('m', 's', 'e', 't')); - _insert_feature("alternate_annotation_forms", HB_TAG('n', 'a', 'l', 't')); - _insert_feature("nlc_kanji_forms", HB_TAG('n', 'l', 'c', 'k')); - _insert_feature("nukta_forms", HB_TAG('n', 'u', 'k', 't')); - _insert_feature("numerators", HB_TAG('n', 'u', 'm', 'r')); - _insert_feature("oldstyle_figures", HB_TAG('o', 'n', 'u', 'm')); - _insert_feature("optical_bounds", HB_TAG('o', 'p', 'b', 'd')); - _insert_feature("ordinals", HB_TAG('o', 'r', 'd', 'n')); - _insert_feature("ornaments", HB_TAG('o', 'r', 'n', 'm')); - _insert_feature("proportional_alternate_widths", HB_TAG('p', 'a', 'l', 't')); - _insert_feature("petite_capitals", HB_TAG('p', 'c', 'a', 'p')); - _insert_feature("proportional_kana", HB_TAG('p', 'k', 'n', 'a')); - _insert_feature("proportional_figures", HB_TAG('p', 'n', 'u', 'm')); - _insert_feature("pre_base_forms", HB_TAG('p', 'r', 'e', 'f')); - _insert_feature("pre_base_substitutions", HB_TAG('p', 'r', 'e', 's')); - _insert_feature("post_base_forms", HB_TAG('p', 's', 't', 'f')); - _insert_feature("post_base_substitutions", HB_TAG('p', 's', 't', 's')); - _insert_feature("proportional_widths", HB_TAG('p', 'w', 'i', 'd')); - _insert_feature("quarter_widths", HB_TAG('q', 'w', 'i', 'd')); - _insert_feature("randomize", HB_TAG('r', 'a', 'n', 'd')); - _insert_feature("required_contextual_alternates", HB_TAG('r', 'c', 'l', 't')); - _insert_feature("rakar_forms", HB_TAG('r', 'k', 'r', 'f')); - _insert_feature("required_ligatures", HB_TAG('r', 'l', 'i', 'g')); - _insert_feature("reph_forms", HB_TAG('r', 'p', 'h', 'f')); - _insert_feature("right_bounds", HB_TAG('r', 't', 'b', 'd')); - _insert_feature("right_to_left_alternates", HB_TAG('r', 't', 'l', 'a')); - _insert_feature("right_to_left_mirrored_forms", HB_TAG('r', 't', 'l', 'm')); - _insert_feature("ruby_notation_forms", HB_TAG('r', 'u', 'b', 'y')); - _insert_feature("required_variation_alternates", HB_TAG('r', 'v', 'r', 'n')); - _insert_feature("stylistic_alternates", HB_TAG('s', 'a', 'l', 't')); - _insert_feature("scientific_inferiors", HB_TAG('s', 'i', 'n', 'f')); - _insert_feature("optical_size", HB_TAG('s', 'i', 'z', 'e')); - _insert_feature("small_capitals", HB_TAG('s', 'm', 'c', 'p')); - _insert_feature("simplified_forms", HB_TAG('s', 'm', 'p', 'l')); - _insert_feature("stylistic_set_01", HB_TAG('s', 's', '0', '1')); - _insert_feature("stylistic_set_02", HB_TAG('s', 's', '0', '2')); - _insert_feature("stylistic_set_03", HB_TAG('s', 's', '0', '3')); - _insert_feature("stylistic_set_04", HB_TAG('s', 's', '0', '4')); - _insert_feature("stylistic_set_05", HB_TAG('s', 's', '0', '5')); - _insert_feature("stylistic_set_06", HB_TAG('s', 's', '0', '6')); - _insert_feature("stylistic_set_07", HB_TAG('s', 's', '0', '7')); - _insert_feature("stylistic_set_08", HB_TAG('s', 's', '0', '8')); - _insert_feature("stylistic_set_09", HB_TAG('s', 's', '0', '9')); - _insert_feature("stylistic_set_10", HB_TAG('s', 's', '1', '0')); - _insert_feature("stylistic_set_11", HB_TAG('s', 's', '1', '1')); - _insert_feature("stylistic_set_12", HB_TAG('s', 's', '1', '2')); - _insert_feature("stylistic_set_13", HB_TAG('s', 's', '1', '3')); - _insert_feature("stylistic_set_14", HB_TAG('s', 's', '1', '4')); - _insert_feature("stylistic_set_15", HB_TAG('s', 's', '1', '5')); - _insert_feature("stylistic_set_16", HB_TAG('s', 's', '1', '6')); - _insert_feature("stylistic_set_17", HB_TAG('s', 's', '1', '7')); - _insert_feature("stylistic_set_18", HB_TAG('s', 's', '1', '8')); - _insert_feature("stylistic_set_19", HB_TAG('s', 's', '1', '9')); - _insert_feature("stylistic_set_20", HB_TAG('s', 's', '2', '0')); - _insert_feature("math_script_style_alternates", HB_TAG('s', 's', 't', 'y')); - _insert_feature("stretching_glyph_decomposition", HB_TAG('s', 't', 'c', 'h')); - _insert_feature("subscript", HB_TAG('s', 'u', 'b', 's')); - _insert_feature("superscript", HB_TAG('s', 'u', 'p', 's')); - _insert_feature("swash", HB_TAG('s', 'w', 's', 'h')); - _insert_feature("titling", HB_TAG('t', 'i', 't', 'l')); - _insert_feature("trailing_jamo_forms", HB_TAG('t', 'j', 'm', 'o')); - _insert_feature("traditional_name_forms", HB_TAG('t', 'n', 'a', 'm')); - _insert_feature("tabular_figures", HB_TAG('t', 'n', 'u', 'm')); - _insert_feature("traditional_forms", HB_TAG('t', 'r', 'a', 'd')); - _insert_feature("third_widths", HB_TAG('t', 'w', 'i', 'd')); - _insert_feature("unicase", HB_TAG('u', 'n', 'i', 'c')); - _insert_feature("alternate_vertical_metrics", HB_TAG('v', 'a', 'l', 't')); - _insert_feature("vattu_variants", HB_TAG('v', 'a', 't', 'u')); - _insert_feature("vertical_writing", HB_TAG('v', 'e', 'r', 't')); - _insert_feature("alternate_vertical_half_metrics", HB_TAG('v', 'h', 'a', 'l')); - _insert_feature("vowel_jamo_forms", HB_TAG('v', 'j', 'm', 'o')); - _insert_feature("vertical_kana_alternates", HB_TAG('v', 'k', 'n', 'a')); - _insert_feature("vertical_kerning", HB_TAG('v', 'k', 'r', 'n')); - _insert_feature("proportional_alternate_vertical_metrics", HB_TAG('v', 'p', 'a', 'l')); - _insert_feature("vertical_alternates_and_rotation", HB_TAG('v', 'r', 't', '2')); - _insert_feature("vertical_alternates_for_rotation", HB_TAG('v', 'r', 't', 'r')); - _insert_feature("slashed_zero", HB_TAG('z', 'e', 'r', 'o')); + // Name, Tag, Data Type, Hidden + _insert_feature("access_all_alternates", HB_TAG('a', 'a', 'l', 't'), Variant::Type::INT, false); + _insert_feature("above_base_forms", HB_TAG('a', 'b', 'v', 'f'), Variant::Type::INT, true); + _insert_feature("above_base_mark_positioning", HB_TAG('a', 'b', 'v', 'm'), Variant::Type::INT, true); + _insert_feature("above_base_substitutions", HB_TAG('a', 'b', 'v', 's'), Variant::Type::INT, true); + _insert_feature("alternative_fractions", HB_TAG('a', 'f', 'r', 'c'), Variant::Type::INT, false); + _insert_feature("akhands", HB_TAG('a', 'k', 'h', 'n'), Variant::Type::INT, true); + _insert_feature("below_base_forms", HB_TAG('b', 'l', 'w', 'f'), Variant::Type::INT, true); + _insert_feature("below_base_mark_positioning", HB_TAG('b', 'l', 'w', 'm'), Variant::Type::INT, true); + _insert_feature("below_base_substitutions", HB_TAG('b', 'l', 'w', 's'), Variant::Type::INT, true); + _insert_feature("contextual_alternates", HB_TAG('c', 'a', 'l', 't'), Variant::Type::BOOL, false); + _insert_feature("case_sensitive_forms", HB_TAG('c', 'a', 's', 'e'), Variant::Type::BOOL, false); + _insert_feature("glyph_composition", HB_TAG('c', 'c', 'm', 'p'), Variant::Type::INT, true); + _insert_feature("conjunct_form_after_ro", HB_TAG('c', 'f', 'a', 'r'), Variant::Type::INT, true); + _insert_feature("contextual_half_width_spacing", HB_TAG('c', 'h', 'w', 's'), Variant::Type::INT, true); + _insert_feature("conjunct_forms", HB_TAG('c', 'j', 'c', 't'), Variant::Type::INT, true); + _insert_feature("contextual_ligatures", HB_TAG('c', 'l', 'i', 'g'), Variant::Type::BOOL, false); + _insert_feature("centered_cjk_punctuation", HB_TAG('c', 'p', 'c', 't'), Variant::Type::BOOL, false); + _insert_feature("capital_spacing", HB_TAG('c', 'p', 's', 'p'), Variant::Type::BOOL, false); + _insert_feature("contextual_swash", HB_TAG('c', 's', 'w', 'h'), Variant::Type::INT, false); + _insert_feature("cursive_positioning", HB_TAG('c', 'u', 'r', 's'), Variant::Type::INT, true); + _insert_feature("character_variant_01", HB_TAG('c', 'v', '0', '1'), Variant::Type::BOOL, false); + _insert_feature("character_variant_02", HB_TAG('c', 'v', '0', '2'), Variant::Type::BOOL, false); + _insert_feature("character_variant_03", HB_TAG('c', 'v', '0', '3'), Variant::Type::BOOL, false); + _insert_feature("character_variant_04", HB_TAG('c', 'v', '0', '4'), Variant::Type::BOOL, false); + _insert_feature("character_variant_05", HB_TAG('c', 'v', '0', '5'), Variant::Type::BOOL, false); + _insert_feature("character_variant_06", HB_TAG('c', 'v', '0', '6'), Variant::Type::BOOL, false); + _insert_feature("character_variant_07", HB_TAG('c', 'v', '0', '7'), Variant::Type::BOOL, false); + _insert_feature("character_variant_08", HB_TAG('c', 'v', '0', '8'), Variant::Type::BOOL, false); + _insert_feature("character_variant_09", HB_TAG('c', 'v', '0', '9'), Variant::Type::BOOL, false); + _insert_feature("character_variant_10", HB_TAG('c', 'v', '1', '0'), Variant::Type::BOOL, false); + _insert_feature("character_variant_11", HB_TAG('c', 'v', '1', '1'), Variant::Type::BOOL, false); + _insert_feature("character_variant_12", HB_TAG('c', 'v', '1', '2'), Variant::Type::BOOL, false); + _insert_feature("character_variant_13", HB_TAG('c', 'v', '1', '3'), Variant::Type::BOOL, false); + _insert_feature("character_variant_14", HB_TAG('c', 'v', '1', '4'), Variant::Type::BOOL, false); + _insert_feature("character_variant_15", HB_TAG('c', 'v', '1', '5'), Variant::Type::BOOL, false); + _insert_feature("character_variant_16", HB_TAG('c', 'v', '1', '6'), Variant::Type::BOOL, false); + _insert_feature("character_variant_17", HB_TAG('c', 'v', '1', '7'), Variant::Type::BOOL, false); + _insert_feature("character_variant_18", HB_TAG('c', 'v', '1', '8'), Variant::Type::BOOL, false); + _insert_feature("character_variant_19", HB_TAG('c', 'v', '1', '9'), Variant::Type::BOOL, false); + _insert_feature("character_variant_20", HB_TAG('c', 'v', '2', '0'), Variant::Type::BOOL, false); + _insert_feature("character_variant_21", HB_TAG('c', 'v', '2', '1'), Variant::Type::BOOL, false); + _insert_feature("character_variant_22", HB_TAG('c', 'v', '2', '2'), Variant::Type::BOOL, false); + _insert_feature("character_variant_23", HB_TAG('c', 'v', '2', '3'), Variant::Type::BOOL, false); + _insert_feature("character_variant_24", HB_TAG('c', 'v', '2', '4'), Variant::Type::BOOL, false); + _insert_feature("character_variant_25", HB_TAG('c', 'v', '2', '5'), Variant::Type::BOOL, false); + _insert_feature("character_variant_26", HB_TAG('c', 'v', '2', '6'), Variant::Type::BOOL, false); + _insert_feature("character_variant_27", HB_TAG('c', 'v', '2', '7'), Variant::Type::BOOL, false); + _insert_feature("character_variant_28", HB_TAG('c', 'v', '2', '8'), Variant::Type::BOOL, false); + _insert_feature("character_variant_29", HB_TAG('c', 'v', '2', '9'), Variant::Type::BOOL, false); + _insert_feature("character_variant_30", HB_TAG('c', 'v', '3', '0'), Variant::Type::BOOL, false); + _insert_feature("character_variant_31", HB_TAG('c', 'v', '3', '1'), Variant::Type::BOOL, false); + _insert_feature("character_variant_32", HB_TAG('c', 'v', '3', '2'), Variant::Type::BOOL, false); + _insert_feature("character_variant_33", HB_TAG('c', 'v', '3', '3'), Variant::Type::BOOL, false); + _insert_feature("character_variant_34", HB_TAG('c', 'v', '3', '4'), Variant::Type::BOOL, false); + _insert_feature("character_variant_35", HB_TAG('c', 'v', '3', '5'), Variant::Type::BOOL, false); + _insert_feature("character_variant_36", HB_TAG('c', 'v', '3', '6'), Variant::Type::BOOL, false); + _insert_feature("character_variant_37", HB_TAG('c', 'v', '3', '7'), Variant::Type::BOOL, false); + _insert_feature("character_variant_38", HB_TAG('c', 'v', '3', '8'), Variant::Type::BOOL, false); + _insert_feature("character_variant_39", HB_TAG('c', 'v', '3', '9'), Variant::Type::BOOL, false); + _insert_feature("character_variant_40", HB_TAG('c', 'v', '4', '0'), Variant::Type::BOOL, false); + _insert_feature("character_variant_41", HB_TAG('c', 'v', '4', '1'), Variant::Type::BOOL, false); + _insert_feature("character_variant_42", HB_TAG('c', 'v', '4', '2'), Variant::Type::BOOL, false); + _insert_feature("character_variant_43", HB_TAG('c', 'v', '4', '3'), Variant::Type::BOOL, false); + _insert_feature("character_variant_44", HB_TAG('c', 'v', '4', '4'), Variant::Type::BOOL, false); + _insert_feature("character_variant_45", HB_TAG('c', 'v', '4', '5'), Variant::Type::BOOL, false); + _insert_feature("character_variant_46", HB_TAG('c', 'v', '4', '6'), Variant::Type::BOOL, false); + _insert_feature("character_variant_47", HB_TAG('c', 'v', '4', '7'), Variant::Type::BOOL, false); + _insert_feature("character_variant_48", HB_TAG('c', 'v', '4', '8'), Variant::Type::BOOL, false); + _insert_feature("character_variant_49", HB_TAG('c', 'v', '4', '9'), Variant::Type::BOOL, false); + _insert_feature("character_variant_50", HB_TAG('c', 'v', '5', '0'), Variant::Type::BOOL, false); + _insert_feature("character_variant_51", HB_TAG('c', 'v', '5', '1'), Variant::Type::BOOL, false); + _insert_feature("character_variant_52", HB_TAG('c', 'v', '5', '2'), Variant::Type::BOOL, false); + _insert_feature("character_variant_53", HB_TAG('c', 'v', '5', '3'), Variant::Type::BOOL, false); + _insert_feature("character_variant_54", HB_TAG('c', 'v', '5', '4'), Variant::Type::BOOL, false); + _insert_feature("character_variant_55", HB_TAG('c', 'v', '5', '5'), Variant::Type::BOOL, false); + _insert_feature("character_variant_56", HB_TAG('c', 'v', '5', '6'), Variant::Type::BOOL, false); + _insert_feature("character_variant_57", HB_TAG('c', 'v', '5', '7'), Variant::Type::BOOL, false); + _insert_feature("character_variant_58", HB_TAG('c', 'v', '5', '8'), Variant::Type::BOOL, false); + _insert_feature("character_variant_59", HB_TAG('c', 'v', '5', '9'), Variant::Type::BOOL, false); + _insert_feature("character_variant_60", HB_TAG('c', 'v', '6', '0'), Variant::Type::BOOL, false); + _insert_feature("character_variant_61", HB_TAG('c', 'v', '6', '1'), Variant::Type::BOOL, false); + _insert_feature("character_variant_62", HB_TAG('c', 'v', '6', '2'), Variant::Type::BOOL, false); + _insert_feature("character_variant_63", HB_TAG('c', 'v', '6', '3'), Variant::Type::BOOL, false); + _insert_feature("character_variant_64", HB_TAG('c', 'v', '6', '4'), Variant::Type::BOOL, false); + _insert_feature("character_variant_65", HB_TAG('c', 'v', '6', '5'), Variant::Type::BOOL, false); + _insert_feature("character_variant_66", HB_TAG('c', 'v', '6', '6'), Variant::Type::BOOL, false); + _insert_feature("character_variant_67", HB_TAG('c', 'v', '6', '7'), Variant::Type::BOOL, false); + _insert_feature("character_variant_68", HB_TAG('c', 'v', '6', '8'), Variant::Type::BOOL, false); + _insert_feature("character_variant_69", HB_TAG('c', 'v', '6', '9'), Variant::Type::BOOL, false); + _insert_feature("character_variant_70", HB_TAG('c', 'v', '7', '0'), Variant::Type::BOOL, false); + _insert_feature("character_variant_71", HB_TAG('c', 'v', '7', '1'), Variant::Type::BOOL, false); + _insert_feature("character_variant_72", HB_TAG('c', 'v', '7', '2'), Variant::Type::BOOL, false); + _insert_feature("character_variant_73", HB_TAG('c', 'v', '7', '3'), Variant::Type::BOOL, false); + _insert_feature("character_variant_74", HB_TAG('c', 'v', '7', '4'), Variant::Type::BOOL, false); + _insert_feature("character_variant_75", HB_TAG('c', 'v', '7', '5'), Variant::Type::BOOL, false); + _insert_feature("character_variant_76", HB_TAG('c', 'v', '7', '6'), Variant::Type::BOOL, false); + _insert_feature("character_variant_77", HB_TAG('c', 'v', '7', '7'), Variant::Type::BOOL, false); + _insert_feature("character_variant_78", HB_TAG('c', 'v', '7', '8'), Variant::Type::BOOL, false); + _insert_feature("character_variant_79", HB_TAG('c', 'v', '7', '9'), Variant::Type::BOOL, false); + _insert_feature("character_variant_80", HB_TAG('c', 'v', '8', '0'), Variant::Type::BOOL, false); + _insert_feature("character_variant_81", HB_TAG('c', 'v', '8', '1'), Variant::Type::BOOL, false); + _insert_feature("character_variant_82", HB_TAG('c', 'v', '8', '2'), Variant::Type::BOOL, false); + _insert_feature("character_variant_83", HB_TAG('c', 'v', '8', '3'), Variant::Type::BOOL, false); + _insert_feature("character_variant_84", HB_TAG('c', 'v', '8', '4'), Variant::Type::BOOL, false); + _insert_feature("character_variant_85", HB_TAG('c', 'v', '8', '5'), Variant::Type::BOOL, false); + _insert_feature("character_variant_86", HB_TAG('c', 'v', '8', '6'), Variant::Type::BOOL, false); + _insert_feature("character_variant_87", HB_TAG('c', 'v', '8', '7'), Variant::Type::BOOL, false); + _insert_feature("character_variant_88", HB_TAG('c', 'v', '8', '8'), Variant::Type::BOOL, false); + _insert_feature("character_variant_89", HB_TAG('c', 'v', '8', '9'), Variant::Type::BOOL, false); + _insert_feature("character_variant_90", HB_TAG('c', 'v', '9', '0'), Variant::Type::BOOL, false); + _insert_feature("character_variant_91", HB_TAG('c', 'v', '9', '1'), Variant::Type::BOOL, false); + _insert_feature("character_variant_92", HB_TAG('c', 'v', '9', '2'), Variant::Type::BOOL, false); + _insert_feature("character_variant_93", HB_TAG('c', 'v', '9', '3'), Variant::Type::BOOL, false); + _insert_feature("character_variant_94", HB_TAG('c', 'v', '9', '4'), Variant::Type::BOOL, false); + _insert_feature("character_variant_95", HB_TAG('c', 'v', '9', '5'), Variant::Type::BOOL, false); + _insert_feature("character_variant_96", HB_TAG('c', 'v', '9', '6'), Variant::Type::BOOL, false); + _insert_feature("character_variant_97", HB_TAG('c', 'v', '9', '7'), Variant::Type::BOOL, false); + _insert_feature("character_variant_98", HB_TAG('c', 'v', '9', '8'), Variant::Type::BOOL, false); + _insert_feature("character_variant_99", HB_TAG('c', 'v', '9', '9'), Variant::Type::BOOL, false); + _insert_feature("petite_capitals_from_capitals", HB_TAG('c', '2', 'p', 'c'), Variant::Type::BOOL, false); + _insert_feature("small_capitals_from_capitals", HB_TAG('c', '2', 's', 'c'), Variant::Type::BOOL, false); + _insert_feature("distances", HB_TAG('d', 'i', 's', 't'), Variant::Type::INT, true); + _insert_feature("discretionary_ligatures", HB_TAG('d', 'l', 'i', 'g'), Variant::Type::BOOL, false); + _insert_feature("denominators", HB_TAG('d', 'n', 'o', 'm'), Variant::Type::BOOL, false); + _insert_feature("dotless_forms", HB_TAG('d', 't', 'l', 's'), Variant::Type::INT, true); + _insert_feature("expert_forms", HB_TAG('e', 'x', 'p', 't'), Variant::Type::BOOL, true); + _insert_feature("final_glyph_on_line_alternates", HB_TAG('f', 'a', 'l', 't'), Variant::Type::INT, false); + _insert_feature("terminal_forms_2", HB_TAG('f', 'i', 'n', '2'), Variant::Type::INT, true); + _insert_feature("terminal_forms_3", HB_TAG('f', 'i', 'n', '3'), Variant::Type::INT, true); + _insert_feature("terminal_forms", HB_TAG('f', 'i', 'n', 'a'), Variant::Type::INT, true); + _insert_feature("flattened_accent_forms", HB_TAG('f', 'l', 'a', 'c'), Variant::Type::INT, true); + _insert_feature("fractions", HB_TAG('f', 'r', 'a', 'c'), Variant::Type::BOOL, false); + _insert_feature("full_widths", HB_TAG('f', 'w', 'i', 'd'), Variant::Type::BOOL, false); + _insert_feature("half_forms", HB_TAG('h', 'a', 'l', 'f'), Variant::Type::INT, true); + _insert_feature("halant_forms", HB_TAG('h', 'a', 'l', 'n'), Variant::Type::INT, true); + _insert_feature("alternate_half_widths", HB_TAG('h', 'a', 'l', 't'), Variant::Type::BOOL, false); + _insert_feature("historical_forms", HB_TAG('h', 'i', 's', 't'), Variant::Type::INT, false); + _insert_feature("horizontal_kana_alternates", HB_TAG('h', 'k', 'n', 'a'), Variant::Type::BOOL, false); + _insert_feature("historical_ligatures", HB_TAG('h', 'l', 'i', 'g'), Variant::Type::BOOL, false); + _insert_feature("hangul", HB_TAG('h', 'n', 'g', 'l'), Variant::Type::INT, false); + _insert_feature("hojo_kanji_forms", HB_TAG('h', 'o', 'j', 'o'), Variant::Type::INT, false); + _insert_feature("half_widths", HB_TAG('h', 'w', 'i', 'd'), Variant::Type::BOOL, false); + _insert_feature("initial_forms", HB_TAG('i', 'n', 'i', 't'), Variant::Type::INT, true); + _insert_feature("isolated_forms", HB_TAG('i', 's', 'o', 'l'), Variant::Type::INT, true); + _insert_feature("italics", HB_TAG('i', 't', 'a', 'l'), Variant::Type::INT, false); + _insert_feature("justification_alternates", HB_TAG('j', 'a', 'l', 't'), Variant::Type::INT, false); + _insert_feature("jis78_forms", HB_TAG('j', 'p', '7', '8'), Variant::Type::INT, false); + _insert_feature("jis83_forms", HB_TAG('j', 'p', '8', '3'), Variant::Type::INT, false); + _insert_feature("jis90_forms", HB_TAG('j', 'p', '9', '0'), Variant::Type::INT, false); + _insert_feature("jis2004_forms", HB_TAG('j', 'p', '0', '4'), Variant::Type::INT, false); + _insert_feature("kerning", HB_TAG('k', 'e', 'r', 'n'), Variant::Type::BOOL, false); + _insert_feature("left_bounds", HB_TAG('l', 'f', 'b', 'd'), Variant::Type::INT, false); + _insert_feature("standard_ligatures", HB_TAG('l', 'i', 'g', 'a'), Variant::Type::BOOL, false); + _insert_feature("leading_jamo_forms", HB_TAG('l', 'j', 'm', 'o'), Variant::Type::INT, true); + _insert_feature("lining_figures", HB_TAG('l', 'n', 'u', 'm'), Variant::Type::INT, false); + _insert_feature("localized_forms", HB_TAG('l', 'o', 'c', 'l'), Variant::Type::INT, true); + _insert_feature("left_to_right_alternates", HB_TAG('l', 't', 'r', 'a'), Variant::Type::INT, true); + _insert_feature("left_to_right_mirrored_forms", HB_TAG('l', 't', 'r', 'm'), Variant::Type::INT, true); + _insert_feature("mark_positioning", HB_TAG('m', 'a', 'r', 'k'), Variant::Type::INT, true); + _insert_feature("medial_forms_2", HB_TAG('m', 'e', 'd', '2'), Variant::Type::INT, true); + _insert_feature("medial_forms", HB_TAG('m', 'e', 'd', 'i'), Variant::Type::INT, true); + _insert_feature("mathematical_greek", HB_TAG('m', 'g', 'r', 'k'), Variant::Type::BOOL, false); + _insert_feature("mark_to_mark_positioning", HB_TAG('m', 'k', 'm', 'k'), Variant::Type::INT, true); + _insert_feature("mark_positioning_via_substitution", HB_TAG('m', 's', 'e', 't'), Variant::Type::INT, true); + _insert_feature("alternate_annotation_forms", HB_TAG('n', 'a', 'l', 't'), Variant::Type::INT, false); + _insert_feature("nlc_kanji_forms", HB_TAG('n', 'l', 'c', 'k'), Variant::Type::INT, false); + _insert_feature("nukta_forms", HB_TAG('n', 'u', 'k', 't'), Variant::Type::INT, true); + _insert_feature("numerators", HB_TAG('n', 'u', 'm', 'r'), Variant::Type::BOOL, false); + _insert_feature("oldstyle_figures", HB_TAG('o', 'n', 'u', 'm'), Variant::Type::INT, false); + _insert_feature("optical_bounds", HB_TAG('o', 'p', 'b', 'd'), Variant::Type::INT, true); + _insert_feature("ordinals", HB_TAG('o', 'r', 'd', 'n'), Variant::Type::BOOL, false); + _insert_feature("ornaments", HB_TAG('o', 'r', 'n', 'm'), Variant::Type::INT, false); + _insert_feature("proportional_alternate_widths", HB_TAG('p', 'a', 'l', 't'), Variant::Type::BOOL, false); + _insert_feature("petite_capitals", HB_TAG('p', 'c', 'a', 'p'), Variant::Type::BOOL, false); + _insert_feature("proportional_kana", HB_TAG('p', 'k', 'n', 'a'), Variant::Type::BOOL, false); + _insert_feature("proportional_figures", HB_TAG('p', 'n', 'u', 'm'), Variant::Type::BOOL, false); + _insert_feature("pre_base_forms", HB_TAG('p', 'r', 'e', 'f'), Variant::Type::INT, true); + _insert_feature("pre_base_substitutions", HB_TAG('p', 'r', 'e', 's'), Variant::Type::INT, true); + _insert_feature("post_base_forms", HB_TAG('p', 's', 't', 'f'), Variant::Type::INT, true); + _insert_feature("post_base_substitutions", HB_TAG('p', 's', 't', 's'), Variant::Type::INT, true); + _insert_feature("proportional_widths", HB_TAG('p', 'w', 'i', 'd'), Variant::Type::BOOL, false); + _insert_feature("quarter_widths", HB_TAG('q', 'w', 'i', 'd'), Variant::Type::BOOL, false); + _insert_feature("randomize", HB_TAG('r', 'a', 'n', 'd'), Variant::Type::INT, false); + _insert_feature("required_contextual_alternates", HB_TAG('r', 'c', 'l', 't'), Variant::Type::BOOL, true); + _insert_feature("rakar_forms", HB_TAG('r', 'k', 'r', 'f'), Variant::Type::INT, true); + _insert_feature("required_ligatures", HB_TAG('r', 'l', 'i', 'g'), Variant::Type::BOOL, true); + _insert_feature("reph_forms", HB_TAG('r', 'p', 'h', 'f'), Variant::Type::INT, true); + _insert_feature("right_bounds", HB_TAG('r', 't', 'b', 'd'), Variant::Type::INT, false); + _insert_feature("right_to_left_alternates", HB_TAG('r', 't', 'l', 'a'), Variant::Type::INT, true); + _insert_feature("right_to_left_mirrored_forms", HB_TAG('r', 't', 'l', 'm'), Variant::Type::INT, true); + _insert_feature("ruby_notation_forms", HB_TAG('r', 'u', 'b', 'y'), Variant::Type::INT, false); + _insert_feature("required_variation_alternates", HB_TAG('r', 'v', 'r', 'n'), Variant::Type::INT, true); + _insert_feature("stylistic_alternates", HB_TAG('s', 'a', 'l', 't'), Variant::Type::INT, false); + _insert_feature("scientific_inferiors", HB_TAG('s', 'i', 'n', 'f'), Variant::Type::BOOL, false); + _insert_feature("optical_size", HB_TAG('s', 'i', 'z', 'e'), Variant::Type::INT, false); + _insert_feature("small_capitals", HB_TAG('s', 'm', 'c', 'p'), Variant::Type::BOOL, false); + _insert_feature("simplified_forms", HB_TAG('s', 'm', 'p', 'l'), Variant::Type::INT, false); + _insert_feature("stylistic_set_01", HB_TAG('s', 's', '0', '1'), Variant::Type::BOOL, false); + _insert_feature("stylistic_set_02", HB_TAG('s', 's', '0', '2'), Variant::Type::BOOL, false); + _insert_feature("stylistic_set_03", HB_TAG('s', 's', '0', '3'), Variant::Type::BOOL, false); + _insert_feature("stylistic_set_04", HB_TAG('s', 's', '0', '4'), Variant::Type::BOOL, false); + _insert_feature("stylistic_set_05", HB_TAG('s', 's', '0', '5'), Variant::Type::BOOL, false); + _insert_feature("stylistic_set_06", HB_TAG('s', 's', '0', '6'), Variant::Type::BOOL, false); + _insert_feature("stylistic_set_07", HB_TAG('s', 's', '0', '7'), Variant::Type::BOOL, false); + _insert_feature("stylistic_set_08", HB_TAG('s', 's', '0', '8'), Variant::Type::BOOL, false); + _insert_feature("stylistic_set_09", HB_TAG('s', 's', '0', '9'), Variant::Type::BOOL, false); + _insert_feature("stylistic_set_10", HB_TAG('s', 's', '1', '0'), Variant::Type::BOOL, false); + _insert_feature("stylistic_set_11", HB_TAG('s', 's', '1', '1'), Variant::Type::BOOL, false); + _insert_feature("stylistic_set_12", HB_TAG('s', 's', '1', '2'), Variant::Type::BOOL, false); + _insert_feature("stylistic_set_13", HB_TAG('s', 's', '1', '3'), Variant::Type::BOOL, false); + _insert_feature("stylistic_set_14", HB_TAG('s', 's', '1', '4'), Variant::Type::BOOL, false); + _insert_feature("stylistic_set_15", HB_TAG('s', 's', '1', '5'), Variant::Type::BOOL, false); + _insert_feature("stylistic_set_16", HB_TAG('s', 's', '1', '6'), Variant::Type::BOOL, false); + _insert_feature("stylistic_set_17", HB_TAG('s', 's', '1', '7'), Variant::Type::BOOL, false); + _insert_feature("stylistic_set_18", HB_TAG('s', 's', '1', '8'), Variant::Type::BOOL, false); + _insert_feature("stylistic_set_19", HB_TAG('s', 's', '1', '9'), Variant::Type::BOOL, false); + _insert_feature("stylistic_set_20", HB_TAG('s', 's', '2', '0'), Variant::Type::BOOL, false); + _insert_feature("math_script_style_alternates", HB_TAG('s', 's', 't', 'y'), Variant::Type::INT, true); + _insert_feature("stretching_glyph_decomposition", HB_TAG('s', 't', 'c', 'h'), Variant::Type::INT, true); + _insert_feature("subscript", HB_TAG('s', 'u', 'b', 's'), Variant::Type::BOOL, false); + _insert_feature("superscript", HB_TAG('s', 'u', 'p', 's'), Variant::Type::BOOL, false); + _insert_feature("swash", HB_TAG('s', 'w', 's', 'h'), Variant::Type::INT, false); + _insert_feature("titling", HB_TAG('t', 'i', 't', 'l'), Variant::Type::BOOL, false); + _insert_feature("trailing_jamo_forms", HB_TAG('t', 'j', 'm', 'o'), Variant::Type::INT, true); + _insert_feature("traditional_name_forms", HB_TAG('t', 'n', 'a', 'm'), Variant::Type::INT, false); + _insert_feature("tabular_figures", HB_TAG('t', 'n', 'u', 'm'), Variant::Type::BOOL, false); + _insert_feature("traditional_forms", HB_TAG('t', 'r', 'a', 'd'), Variant::Type::INT, false); + _insert_feature("third_widths", HB_TAG('t', 'w', 'i', 'd'), Variant::Type::BOOL, false); + _insert_feature("unicase", HB_TAG('u', 'n', 'i', 'c'), Variant::Type::BOOL, false); + _insert_feature("alternate_vertical_metrics", HB_TAG('v', 'a', 'l', 't'), Variant::Type::INT, false); + _insert_feature("vattu_variants", HB_TAG('v', 'a', 't', 'u'), Variant::Type::INT, true); + _insert_feature("vertical_contextual_half_width_spacing", HB_TAG('v', 'c', 'h', 'w'), Variant::Type::BOOL, false); + _insert_feature("vertical_alternates", HB_TAG('v', 'e', 'r', 't'), Variant::Type::INT, false); + _insert_feature("alternate_vertical_half_metrics", HB_TAG('v', 'h', 'a', 'l'), Variant::Type::BOOL, false); + _insert_feature("vowel_jamo_forms", HB_TAG('v', 'j', 'm', 'o'), Variant::Type::INT, true); + _insert_feature("vertical_kana_alternates", HB_TAG('v', 'k', 'n', 'a'), Variant::Type::INT, false); + _insert_feature("vertical_kerning", HB_TAG('v', 'k', 'r', 'n'), Variant::Type::BOOL, false); + _insert_feature("proportional_alternate_vertical_metrics", HB_TAG('v', 'p', 'a', 'l'), Variant::Type::BOOL, false); + _insert_feature("vertical_alternates_and_rotation", HB_TAG('v', 'r', 't', '2'), Variant::Type::INT, false); + _insert_feature("vertical_alternates_for_rotation", HB_TAG('v', 'r', 't', 'r'), Variant::Type::INT, false); + _insert_feature("slashed_zero", HB_TAG('z', 'e', 'r', 'o'), Variant::Type::BOOL, false); // Registered OpenType variation tag. - _insert_feature("italic", HB_TAG('i', 't', 'a', 'l')); - _insert_feature("optical_size", HB_TAG('o', 'p', 's', 'z')); - _insert_feature("slant", HB_TAG('s', 'l', 'n', 't')); - _insert_feature("width", HB_TAG('w', 'd', 't', 'h')); - _insert_feature("weight", HB_TAG('w', 'g', 'h', 't')); + _insert_feature("italic", HB_TAG('i', 't', 'a', 'l'), Variant::Type::INT, false); + _insert_feature("optical_size", HB_TAG('o', 'p', 's', 'z'), Variant::Type::INT, false); + _insert_feature("slant", HB_TAG('s', 'l', 'n', 't'), Variant::Type::INT, false); + _insert_feature("width", HB_TAG('w', 'd', 't', 'h'), Variant::Type::INT, false); + _insert_feature("weight", HB_TAG('w', 'g', 'h', 't'), Variant::Type::INT, false); } int64_t TextServerAdvanced::name_to_tag(const String &p_name) const { @@ -740,9 +749,23 @@ int64_t TextServerAdvanced::name_to_tag(const String &p_name) const { return hb_tag_from_string(p_name.replace("custom_", "").ascii().get_data(), -1); } +Variant::Type TextServerAdvanced::_get_tag_type(int64_t p_tag) const { + if (feature_sets_inv.has(p_tag)) { + return feature_sets_inv[p_tag].vtype; + } + return Variant::Type::INT; +} + +bool TextServerAdvanced::_get_tag_hidden(int64_t p_tag) const { + if (feature_sets_inv.has(p_tag)) { + return feature_sets_inv[p_tag].hidden; + } + return false; +} + String TextServerAdvanced::tag_to_name(int64_t p_tag) const { if (feature_sets_inv.has(p_tag)) { - return feature_sets_inv[p_tag]; + return feature_sets_inv[p_tag].name; } // No readable name, use tag string. @@ -756,7 +779,7 @@ String TextServerAdvanced::tag_to_name(int64_t p_tag) const { /* Font Glyph Rendering */ /*************************************************************************/ -_FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_texture_pos_for_glyph(FontDataForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const { +_FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_texture_pos_for_glyph(FontForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const { FontTexturePosition ret; ret.index = -1; @@ -953,7 +976,7 @@ void TextServerAdvanced::_generateMTSDF_threaded(uint32_t y, void *p_td) const { } } -_FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf(FontDataAdvanced *p_font_data, FontDataForSizeAdvanced *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const { +_FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf(FontAdvanced *p_font_data, FontForSizeAdvanced *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const { msdfgen::Shape shape; shape.contours.clear(); @@ -1017,10 +1040,8 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf( td.projection = &projection; td.distancePixelConversion = &distancePixelConversion; - if (p_font_data->work_pool.get_thread_count() == 0) { - p_font_data->work_pool.init(); - } - p_font_data->work_pool.do_work(h, this, &TextServerAdvanced::_generateMTSDF_threaded, &td); + WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &TextServerAdvanced::_generateMTSDF_threaded, &td, h, -1, true, SNAME("FontServerRasterizeMSDF")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task); msdfgen::msdfErrorCorrection(image, shape, projection, p_pixel_range, config); @@ -1059,7 +1080,7 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf( #endif #ifdef MODULE_FREETYPE_ENABLED -_FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitmap(FontDataForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const { +_FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitmap(FontForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const { int w = bitmap.width; int h = bitmap.rows; @@ -1136,12 +1157,12 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma /* Font Cache */ /*************************************************************************/ -_FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontDataAdvanced *p_font_data, const Vector2i &p_size, int32_t p_glyph) const { +_FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontAdvanced *p_font_data, const Vector2i &p_size, int32_t p_glyph) const { ERR_FAIL_COND_V(!_ensure_cache_for_size(p_font_data, p_size), false); int32_t glyph_index = p_glyph & 0xffffff; // Remove subpixel shifts. - FontDataForSizeAdvanced *fd = p_font_data->cache[p_size]; + FontForSizeAdvanced *fd = p_font_data->cache[p_size]; if (fd->glyph_map.has(p_glyph)) { return fd->glyph_map[p_glyph].found; } @@ -1260,13 +1281,13 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontDataAdvanced *p_font_d return false; } -_FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontDataAdvanced *p_font_data, const Vector2i &p_size) const { +_FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_font_data, const Vector2i &p_size) const { ERR_FAIL_COND_V(p_size.x <= 0, false); if (p_font_data->cache.has(p_size)) { return true; } - FontDataForSizeAdvanced *fd = memnew(FontDataForSizeAdvanced); + FontForSizeAdvanced *fd = memnew(FontForSizeAdvanced); fd->size = p_size; if (p_font_data->data_ptr && (p_font_data->data_size > 0)) { // Init dynamic font. @@ -1350,29 +1371,31 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontDataAdvanced } p_font_data->style_flags = 0; if (fd->face->style_flags & FT_STYLE_FLAG_BOLD) { - p_font_data->style_flags |= FONT_BOLD; + p_font_data->style_flags.set_flag(FONT_BOLD); } if (fd->face->style_flags & FT_STYLE_FLAG_ITALIC) { - p_font_data->style_flags |= FONT_ITALIC; + p_font_data->style_flags.set_flag(FONT_ITALIC); } if (fd->face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) { - p_font_data->style_flags |= FONT_FIXED_WIDTH; + p_font_data->style_flags.set_flag(FONT_FIXED_WIDTH); } + + hb_face_t *hb_face = hb_font_get_face(fd->hb_handle); // Get supported scripts from OpenType font data. p_font_data->supported_scripts.clear(); - unsigned int count = hb_ot_layout_table_get_script_tags(hb_font_get_face(fd->hb_handle), HB_OT_TAG_GSUB, 0, nullptr, nullptr); + unsigned int count = hb_ot_layout_table_get_script_tags(hb_face, HB_OT_TAG_GSUB, 0, nullptr, nullptr); if (count != 0) { hb_tag_t *script_tags = (hb_tag_t *)memalloc(count * sizeof(hb_tag_t)); - hb_ot_layout_table_get_script_tags(hb_font_get_face(fd->hb_handle), HB_OT_TAG_GSUB, 0, &count, script_tags); + hb_ot_layout_table_get_script_tags(hb_face, HB_OT_TAG_GSUB, 0, &count, script_tags); for (unsigned int i = 0; i < count; i++) { p_font_data->supported_scripts.insert(script_tags[i]); } memfree(script_tags); } - count = hb_ot_layout_table_get_script_tags(hb_font_get_face(fd->hb_handle), HB_OT_TAG_GPOS, 0, nullptr, nullptr); + count = hb_ot_layout_table_get_script_tags(hb_face, HB_OT_TAG_GPOS, 0, nullptr, nullptr); if (count != 0) { hb_tag_t *script_tags = (hb_tag_t *)memalloc(count * sizeof(hb_tag_t)); - hb_ot_layout_table_get_script_tags(hb_font_get_face(fd->hb_handle), HB_OT_TAG_GPOS, 0, &count, script_tags); + hb_ot_layout_table_get_script_tags(hb_face, HB_OT_TAG_GPOS, 0, &count, script_tags); for (unsigned int i = 0; i < count; i++) { p_font_data->supported_scripts.insert(script_tags[i]); } @@ -1596,21 +1619,49 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontDataAdvanced // Read OpenType feature tags. p_font_data->supported_features.clear(); - count = hb_ot_layout_table_get_feature_tags(hb_font_get_face(fd->hb_handle), HB_OT_TAG_GSUB, 0, nullptr, nullptr); + count = hb_ot_layout_table_get_feature_tags(hb_face, HB_OT_TAG_GSUB, 0, nullptr, nullptr); if (count != 0) { hb_tag_t *feature_tags = (hb_tag_t *)memalloc(count * sizeof(hb_tag_t)); - hb_ot_layout_table_get_feature_tags(hb_font_get_face(fd->hb_handle), HB_OT_TAG_GSUB, 0, &count, feature_tags); + hb_ot_layout_table_get_feature_tags(hb_face, HB_OT_TAG_GSUB, 0, &count, feature_tags); for (unsigned int i = 0; i < count; i++) { - p_font_data->supported_features[feature_tags[i]] = 1; + Dictionary ftr; + + hb_ot_name_id_t lbl_id; + if (hb_ot_layout_feature_get_name_ids(hb_face, HB_OT_TAG_GSUB, i, &lbl_id, nullptr, nullptr, nullptr, nullptr)) { + PackedInt32Array lbl; + unsigned int text_size = hb_ot_name_get_utf32(hb_face, lbl_id, hb_language_from_string(TranslationServer::get_singleton()->get_tool_locale().ascii().get_data(), -1), nullptr, nullptr) + 1; + lbl.resize(text_size); + memset((uint32_t *)lbl.ptrw(), 0, sizeof(uint32_t) * text_size); + hb_ot_name_get_utf32(hb_face, lbl_id, hb_language_from_string(TranslationServer::get_singleton()->get_tool_locale().ascii().get_data(), -1), &text_size, (uint32_t *)lbl.ptrw()); + ftr["label"] = String((const char32_t *)lbl.ptr()); + } + ftr["type"] = _get_tag_type(feature_tags[i]); + ftr["hidden"] = _get_tag_hidden(feature_tags[i]); + + p_font_data->supported_features[feature_tags[i]] = ftr; } memfree(feature_tags); } - count = hb_ot_layout_table_get_feature_tags(hb_font_get_face(fd->hb_handle), HB_OT_TAG_GPOS, 0, nullptr, nullptr); + count = hb_ot_layout_table_get_feature_tags(hb_face, HB_OT_TAG_GPOS, 0, nullptr, nullptr); if (count != 0) { hb_tag_t *feature_tags = (hb_tag_t *)memalloc(count * sizeof(hb_tag_t)); - hb_ot_layout_table_get_feature_tags(hb_font_get_face(fd->hb_handle), HB_OT_TAG_GPOS, 0, &count, feature_tags); + hb_ot_layout_table_get_feature_tags(hb_face, HB_OT_TAG_GPOS, 0, &count, feature_tags); for (unsigned int i = 0; i < count; i++) { - p_font_data->supported_features[feature_tags[i]] = 1; + Dictionary ftr; + + hb_ot_name_id_t lbl_id; + if (hb_ot_layout_feature_get_name_ids(hb_face, HB_OT_TAG_GPOS, i, &lbl_id, nullptr, nullptr, nullptr, nullptr)) { + PackedInt32Array lbl; + unsigned int text_size = hb_ot_name_get_utf32(hb_face, lbl_id, hb_language_from_string(TranslationServer::get_singleton()->get_tool_locale().ascii().get_data(), -1), nullptr, nullptr) + 1; + lbl.resize(text_size); + memset((uint32_t *)lbl.ptrw(), 0, sizeof(uint32_t) * text_size); + hb_ot_name_get_utf32(hb_face, lbl_id, hb_language_from_string(TranslationServer::get_singleton()->get_tool_locale().ascii().get_data(), -1), &text_size, (uint32_t *)lbl.ptrw()); + ftr["label"] = String((const char32_t *)lbl.ptr()); + } + ftr["type"] = _get_tag_type(feature_tags[i]); + ftr["hidden"] = _get_tag_hidden(feature_tags[i]); + + p_font_data->supported_features[feature_tags[i]] = ftr; } memfree(feature_tags); } @@ -1676,8 +1727,8 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontDataAdvanced return true; } -_FORCE_INLINE_ void TextServerAdvanced::_font_clear_cache(FontDataAdvanced *p_font_data) { - for (const KeyValue<Vector2i, FontDataForSizeAdvanced *> &E : p_font_data->cache) { +_FORCE_INLINE_ void TextServerAdvanced::_font_clear_cache(FontAdvanced *p_font_data) { + for (const KeyValue<Vector2i, FontForSizeAdvanced *> &E : p_font_data->cache) { memdelete(E.value); } p_font_data->cache.clear(); @@ -1688,7 +1739,7 @@ _FORCE_INLINE_ void TextServerAdvanced::_font_clear_cache(FontDataAdvanced *p_fo } hb_font_t *TextServerAdvanced::_font_get_hb_handle(const RID &p_font_rid, int64_t p_size) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, nullptr); MutexLock lock(fd->mutex); @@ -1702,13 +1753,13 @@ hb_font_t *TextServerAdvanced::_font_get_hb_handle(const RID &p_font_rid, int64_ RID TextServerAdvanced::create_font() { _THREAD_SAFE_METHOD_ - FontDataAdvanced *fd = memnew(FontDataAdvanced); + FontAdvanced *fd = memnew(FontAdvanced); return font_owner.make_rid(fd); } void TextServerAdvanced::font_set_data(const RID &p_font_rid, const PackedByteArray &p_data) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1719,7 +1770,7 @@ void TextServerAdvanced::font_set_data(const RID &p_font_rid, const PackedByteAr } void TextServerAdvanced::font_set_data_ptr(const RID &p_font_rid, const uint8_t *p_data_ptr, int64_t p_data_size) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1733,7 +1784,7 @@ void TextServerAdvanced::font_set_face_index(const RID &p_font_rid, int64_t p_fa ERR_FAIL_COND(p_face_index < 0); ERR_FAIL_COND(p_face_index >= 0x7FFF); - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1744,7 +1795,7 @@ void TextServerAdvanced::font_set_face_index(const RID &p_font_rid, int64_t p_fa } int64_t TextServerAdvanced::font_get_face_index(const RID &p_font_rid) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0); MutexLock lock(fd->mutex); @@ -1752,7 +1803,7 @@ int64_t TextServerAdvanced::font_get_face_index(const RID &p_font_rid) const { } int64_t TextServerAdvanced::font_get_face_count(const RID &p_font_rid) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0); MutexLock lock(fd->mutex); @@ -1792,8 +1843,8 @@ int64_t TextServerAdvanced::font_get_face_count(const RID &p_font_rid) const { return face_count; } -void TextServerAdvanced::font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); +void TextServerAdvanced::font_set_style(const RID &p_font_rid, BitField<FontStyle> p_style) { + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1802,8 +1853,8 @@ void TextServerAdvanced::font_set_style(const RID &p_font_rid, int64_t /*FontSty fd->style_flags = p_style; } -int64_t /*FontStyle*/ TextServerAdvanced::font_get_style(const RID &p_font_rid) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); +BitField<TextServer::FontStyle> TextServerAdvanced::font_get_style(const RID &p_font_rid) const { + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0); MutexLock lock(fd->mutex); @@ -1813,7 +1864,7 @@ int64_t /*FontStyle*/ TextServerAdvanced::font_get_style(const RID &p_font_rid) } void TextServerAdvanced::font_set_style_name(const RID &p_font_rid, const String &p_name) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1823,7 +1874,7 @@ void TextServerAdvanced::font_set_style_name(const RID &p_font_rid, const String } String TextServerAdvanced::font_get_style_name(const RID &p_font_rid) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, String()); MutexLock lock(fd->mutex); @@ -1833,7 +1884,7 @@ String TextServerAdvanced::font_get_style_name(const RID &p_font_rid) const { } void TextServerAdvanced::font_set_name(const RID &p_font_rid, const String &p_name) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1843,7 +1894,7 @@ void TextServerAdvanced::font_set_name(const RID &p_font_rid, const String &p_na } String TextServerAdvanced::font_get_name(const RID &p_font_rid) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, String()); MutexLock lock(fd->mutex); @@ -1853,7 +1904,7 @@ String TextServerAdvanced::font_get_name(const RID &p_font_rid) const { } void TextServerAdvanced::font_set_antialiased(const RID &p_font_rid, bool p_antialiased) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1864,7 +1915,7 @@ void TextServerAdvanced::font_set_antialiased(const RID &p_font_rid, bool p_anti } bool TextServerAdvanced::font_is_antialiased(const RID &p_font_rid) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -1872,12 +1923,12 @@ bool TextServerAdvanced::font_is_antialiased(const RID &p_font_rid) const { } void TextServerAdvanced::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); if (fd->mipmaps != p_generate_mipmaps) { - for (KeyValue<Vector2i, FontDataForSizeAdvanced *> &E : fd->cache) { + for (KeyValue<Vector2i, FontForSizeAdvanced *> &E : fd->cache) { for (int i = 0; i < E.value->textures.size(); i++) { E.value->textures.write[i].dirty = true; } @@ -1887,7 +1938,7 @@ void TextServerAdvanced::font_set_generate_mipmaps(const RID &p_font_rid, bool p } bool TextServerAdvanced::font_get_generate_mipmaps(const RID &p_font_rid) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -1895,7 +1946,7 @@ bool TextServerAdvanced::font_get_generate_mipmaps(const RID &p_font_rid) const } void TextServerAdvanced::font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1906,7 +1957,7 @@ void TextServerAdvanced::font_set_multichannel_signed_distance_field(const RID & } bool TextServerAdvanced::font_is_multichannel_signed_distance_field(const RID &p_font_rid) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -1914,7 +1965,7 @@ bool TextServerAdvanced::font_is_multichannel_signed_distance_field(const RID &p } void TextServerAdvanced::font_set_msdf_pixel_range(const RID &p_font_rid, int64_t p_msdf_pixel_range) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1925,7 +1976,7 @@ void TextServerAdvanced::font_set_msdf_pixel_range(const RID &p_font_rid, int64_ } int64_t TextServerAdvanced::font_get_msdf_pixel_range(const RID &p_font_rid) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -1933,7 +1984,7 @@ int64_t TextServerAdvanced::font_get_msdf_pixel_range(const RID &p_font_rid) con } void TextServerAdvanced::font_set_msdf_size(const RID &p_font_rid, int64_t p_msdf_size) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1944,7 +1995,7 @@ void TextServerAdvanced::font_set_msdf_size(const RID &p_font_rid, int64_t p_msd } int64_t TextServerAdvanced::font_get_msdf_size(const RID &p_font_rid) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -1952,7 +2003,7 @@ int64_t TextServerAdvanced::font_get_msdf_size(const RID &p_font_rid) const { } void TextServerAdvanced::font_set_fixed_size(const RID &p_font_rid, int64_t p_fixed_size) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1960,7 +2011,7 @@ void TextServerAdvanced::font_set_fixed_size(const RID &p_font_rid, int64_t p_fi } int64_t TextServerAdvanced::font_get_fixed_size(const RID &p_font_rid) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -1968,7 +2019,7 @@ int64_t TextServerAdvanced::font_get_fixed_size(const RID &p_font_rid) const { } void TextServerAdvanced::font_set_force_autohinter(const RID &p_font_rid, bool p_force_autohinter) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1979,7 +2030,7 @@ void TextServerAdvanced::font_set_force_autohinter(const RID &p_font_rid, bool p } bool TextServerAdvanced::font_is_force_autohinter(const RID &p_font_rid) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -1987,7 +2038,7 @@ bool TextServerAdvanced::font_is_force_autohinter(const RID &p_font_rid) const { } void TextServerAdvanced::font_set_hinting(const RID &p_font_rid, TextServer::Hinting p_hinting) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1998,7 +2049,7 @@ void TextServerAdvanced::font_set_hinting(const RID &p_font_rid, TextServer::Hin } TextServer::Hinting TextServerAdvanced::font_get_hinting(const RID &p_font_rid) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, HINTING_NONE); MutexLock lock(fd->mutex); @@ -2006,7 +2057,7 @@ TextServer::Hinting TextServerAdvanced::font_get_hinting(const RID &p_font_rid) } void TextServerAdvanced::font_set_subpixel_positioning(const RID &p_font_rid, TextServer::SubpixelPositioning p_subpixel) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2014,7 +2065,7 @@ void TextServerAdvanced::font_set_subpixel_positioning(const RID &p_font_rid, Te } TextServer::SubpixelPositioning TextServerAdvanced::font_get_subpixel_positioning(const RID &p_font_rid) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, SUBPIXEL_POSITIONING_DISABLED); MutexLock lock(fd->mutex); @@ -2022,7 +2073,7 @@ TextServer::SubpixelPositioning TextServerAdvanced::font_get_subpixel_positionin } void TextServerAdvanced::font_set_embolden(const RID &p_font_rid, double p_strength) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2033,7 +2084,7 @@ void TextServerAdvanced::font_set_embolden(const RID &p_font_rid, double p_stren } double TextServerAdvanced::font_get_embolden(const RID &p_font_rid) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0.0); MutexLock lock(fd->mutex); @@ -2041,7 +2092,7 @@ double TextServerAdvanced::font_get_embolden(const RID &p_font_rid) const { } void TextServerAdvanced::font_set_transform(const RID &p_font_rid, const Transform2D &p_transform) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2052,7 +2103,7 @@ void TextServerAdvanced::font_set_transform(const RID &p_font_rid, const Transfo } Transform2D TextServerAdvanced::font_get_transform(const RID &p_font_rid) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Transform2D()); MutexLock lock(fd->mutex); @@ -2060,7 +2111,7 @@ Transform2D TextServerAdvanced::font_get_transform(const RID &p_font_rid) const } void TextServerAdvanced::font_set_variation_coordinates(const RID &p_font_rid, const Dictionary &p_variation_coordinates) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2071,7 +2122,7 @@ void TextServerAdvanced::font_set_variation_coordinates(const RID &p_font_rid, c } Dictionary TextServerAdvanced::font_get_variation_coordinates(const RID &p_font_rid) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Dictionary()); MutexLock lock(fd->mutex); @@ -2079,7 +2130,7 @@ Dictionary TextServerAdvanced::font_get_variation_coordinates(const RID &p_font_ } void TextServerAdvanced::font_set_oversampling(const RID &p_font_rid, double p_oversampling) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2090,7 +2141,7 @@ void TextServerAdvanced::font_set_oversampling(const RID &p_font_rid, double p_o } double TextServerAdvanced::font_get_oversampling(const RID &p_font_rid) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0.0); MutexLock lock(fd->mutex); @@ -2098,30 +2149,30 @@ double TextServerAdvanced::font_get_oversampling(const RID &p_font_rid) const { } Array TextServerAdvanced::font_get_size_cache_list(const RID &p_font_rid) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Array()); MutexLock lock(fd->mutex); Array ret; - for (const KeyValue<Vector2i, FontDataForSizeAdvanced *> &E : fd->cache) { + for (const KeyValue<Vector2i, FontForSizeAdvanced *> &E : fd->cache) { ret.push_back(E.key); } return ret; } void TextServerAdvanced::font_clear_size_cache(const RID &p_font_rid) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); - for (const KeyValue<Vector2i, FontDataForSizeAdvanced *> &E : fd->cache) { + for (const KeyValue<Vector2i, FontForSizeAdvanced *> &E : fd->cache) { memdelete(E.value); } fd->cache.clear(); } void TextServerAdvanced::font_remove_size_cache(const RID &p_font_rid, const Vector2i &p_size) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2132,7 +2183,7 @@ void TextServerAdvanced::font_remove_size_cache(const RID &p_font_rid, const Vec } void TextServerAdvanced::font_set_ascent(const RID &p_font_rid, int64_t p_size, double p_ascent) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2143,7 +2194,7 @@ void TextServerAdvanced::font_set_ascent(const RID &p_font_rid, int64_t p_size, } double TextServerAdvanced::font_get_ascent(const RID &p_font_rid, int64_t p_size) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0.0); MutexLock lock(fd->mutex); @@ -2159,7 +2210,7 @@ double TextServerAdvanced::font_get_ascent(const RID &p_font_rid, int64_t p_size } void TextServerAdvanced::font_set_descent(const RID &p_font_rid, int64_t p_size, double p_descent) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); Vector2i size = _get_size(fd, p_size); @@ -2169,7 +2220,7 @@ void TextServerAdvanced::font_set_descent(const RID &p_font_rid, int64_t p_size, } double TextServerAdvanced::font_get_descent(const RID &p_font_rid, int64_t p_size) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0.0); MutexLock lock(fd->mutex); @@ -2185,7 +2236,7 @@ double TextServerAdvanced::font_get_descent(const RID &p_font_rid, int64_t p_siz } void TextServerAdvanced::font_set_underline_position(const RID &p_font_rid, int64_t p_size, double p_underline_position) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2196,7 +2247,7 @@ void TextServerAdvanced::font_set_underline_position(const RID &p_font_rid, int6 } double TextServerAdvanced::font_get_underline_position(const RID &p_font_rid, int64_t p_size) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0.0); MutexLock lock(fd->mutex); @@ -2212,7 +2263,7 @@ double TextServerAdvanced::font_get_underline_position(const RID &p_font_rid, in } void TextServerAdvanced::font_set_underline_thickness(const RID &p_font_rid, int64_t p_size, double p_underline_thickness) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2223,7 +2274,7 @@ void TextServerAdvanced::font_set_underline_thickness(const RID &p_font_rid, int } double TextServerAdvanced::font_get_underline_thickness(const RID &p_font_rid, int64_t p_size) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0.0); MutexLock lock(fd->mutex); @@ -2239,7 +2290,7 @@ double TextServerAdvanced::font_get_underline_thickness(const RID &p_font_rid, i } void TextServerAdvanced::font_set_scale(const RID &p_font_rid, int64_t p_size, double p_scale) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2255,7 +2306,7 @@ void TextServerAdvanced::font_set_scale(const RID &p_font_rid, int64_t p_size, d } double TextServerAdvanced::font_get_scale(const RID &p_font_rid, int64_t p_size) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0.0); MutexLock lock(fd->mutex); @@ -2270,60 +2321,8 @@ double TextServerAdvanced::font_get_scale(const RID &p_font_rid, int64_t p_size) } } -void TextServerAdvanced::font_set_spacing(const RID &p_font_rid, int64_t p_size, TextServer::SpacingType p_spacing, int64_t p_value) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); - ERR_FAIL_COND(!fd); - - MutexLock lock(fd->mutex); - Vector2i size = _get_size(fd, p_size); - - ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); - switch (p_spacing) { - case TextServer::SPACING_GLYPH: { - fd->cache[size]->spacing_glyph = p_value; - } break; - case TextServer::SPACING_SPACE: { - fd->cache[size]->spacing_space = p_value; - } break; - default: { - ERR_FAIL_MSG("Invalid spacing type: " + String::num_int64(p_spacing)); - } break; - } -} - -int64_t TextServerAdvanced::font_get_spacing(const RID &p_font_rid, int64_t p_size, TextServer::SpacingType p_spacing) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); - ERR_FAIL_COND_V(!fd, 0); - - MutexLock lock(fd->mutex); - Vector2i size = _get_size(fd, p_size); - - ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0); - - switch (p_spacing) { - case TextServer::SPACING_GLYPH: { - if (fd->msdf) { - return fd->cache[size]->spacing_glyph * (double)p_size / (double)fd->msdf_source_size; - } else { - return fd->cache[size]->spacing_glyph; - } - } break; - case TextServer::SPACING_SPACE: { - if (fd->msdf) { - return fd->cache[size]->spacing_space * (double)p_size / (double)fd->msdf_source_size; - } else { - return fd->cache[size]->spacing_space; - } - } break; - default: { - ERR_FAIL_V_MSG(0, "Invalid spacing type: " + String::num_int64(p_spacing)); - } break; - } - return 0; -} - int64_t TextServerAdvanced::font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0); MutexLock lock(fd->mutex); @@ -2335,7 +2334,7 @@ int64_t TextServerAdvanced::font_get_texture_count(const RID &p_font_rid, const } void TextServerAdvanced::font_clear_textures(const RID &p_font_rid, const Vector2i &p_size) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); Vector2i size = _get_size_outline(fd, p_size); @@ -2345,7 +2344,7 @@ void TextServerAdvanced::font_clear_textures(const RID &p_font_rid, const Vector } void TextServerAdvanced::font_remove_texture(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2357,7 +2356,7 @@ void TextServerAdvanced::font_remove_texture(const RID &p_font_rid, const Vector } void TextServerAdvanced::font_set_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const Ref<Image> &p_image) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); ERR_FAIL_COND(p_image.is_null()); @@ -2383,14 +2382,12 @@ void TextServerAdvanced::font_set_texture_image(const RID &p_font_rid, const Vec img->generate_mipmaps(); } - tex.texture = Ref<ImageTexture>(); - tex.texture.instantiate(); - tex.texture->create_from_image(img); + tex.texture = ImageTexture::create_from_image(img); tex.dirty = false; } Ref<Image> TextServerAdvanced::font_get_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Ref<Image>()); MutexLock lock(fd->mutex); @@ -2407,7 +2404,7 @@ Ref<Image> TextServerAdvanced::font_get_texture_image(const RID &p_font_rid, con } void TextServerAdvanced::font_set_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const PackedInt32Array &p_offset) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2423,7 +2420,7 @@ void TextServerAdvanced::font_set_texture_offsets(const RID &p_font_rid, const V } PackedInt32Array TextServerAdvanced::font_get_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, PackedInt32Array()); MutexLock lock(fd->mutex); @@ -2436,7 +2433,7 @@ PackedInt32Array TextServerAdvanced::font_get_texture_offsets(const RID &p_font_ } Array TextServerAdvanced::font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Array()); MutexLock lock(fd->mutex); @@ -2452,7 +2449,7 @@ Array TextServerAdvanced::font_get_glyph_list(const RID &p_font_rid, const Vecto } void TextServerAdvanced::font_clear_glyphs(const RID &p_font_rid, const Vector2i &p_size) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2463,7 +2460,7 @@ void TextServerAdvanced::font_clear_glyphs(const RID &p_font_rid, const Vector2i } void TextServerAdvanced::font_remove_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2474,7 +2471,7 @@ void TextServerAdvanced::font_remove_glyph(const RID &p_font_rid, const Vector2i } double TextServerAdvanced::_get_extra_advance(RID p_font_rid, int p_font_size) const { - const FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + const FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0.0); MutexLock lock(fd->mutex); @@ -2488,7 +2485,7 @@ double TextServerAdvanced::_get_extra_advance(RID p_font_rid, int p_font_size) c } Vector2 TextServerAdvanced::font_get_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Vector2()); MutexLock lock(fd->mutex); @@ -2516,7 +2513,7 @@ Vector2 TextServerAdvanced::font_get_glyph_advance(const RID &p_font_rid, int64_ } void TextServerAdvanced::font_set_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph, const Vector2 &p_advance) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2531,7 +2528,7 @@ void TextServerAdvanced::font_set_glyph_advance(const RID &p_font_rid, int64_t p } Vector2 TextServerAdvanced::font_get_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Vector2()); MutexLock lock(fd->mutex); @@ -2552,7 +2549,7 @@ Vector2 TextServerAdvanced::font_get_glyph_offset(const RID &p_font_rid, const V } void TextServerAdvanced::font_set_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_offset) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2567,7 +2564,7 @@ void TextServerAdvanced::font_set_glyph_offset(const RID &p_font_rid, const Vect } Vector2 TextServerAdvanced::font_get_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Vector2()); MutexLock lock(fd->mutex); @@ -2588,7 +2585,7 @@ Vector2 TextServerAdvanced::font_get_glyph_size(const RID &p_font_rid, const Vec } void TextServerAdvanced::font_set_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_gl_size) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2603,7 +2600,7 @@ void TextServerAdvanced::font_set_glyph_size(const RID &p_font_rid, const Vector } Rect2 TextServerAdvanced::font_get_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Rect2()); MutexLock lock(fd->mutex); @@ -2619,7 +2616,7 @@ Rect2 TextServerAdvanced::font_get_glyph_uv_rect(const RID &p_font_rid, const Ve } void TextServerAdvanced::font_set_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Rect2 &p_uv_rect) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2634,7 +2631,7 @@ void TextServerAdvanced::font_set_glyph_uv_rect(const RID &p_font_rid, const Vec } int64_t TextServerAdvanced::font_get_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, -1); MutexLock lock(fd->mutex); @@ -2650,7 +2647,7 @@ int64_t TextServerAdvanced::font_get_glyph_texture_idx(const RID &p_font_rid, co } void TextServerAdvanced::font_set_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, int64_t p_texture_idx) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2665,7 +2662,7 @@ void TextServerAdvanced::font_set_glyph_texture_idx(const RID &p_font_rid, const } RID TextServerAdvanced::font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, RID()); MutexLock lock(fd->mutex); @@ -2690,8 +2687,7 @@ RID TextServerAdvanced::font_get_glyph_texture_rid(const RID &p_font_rid, const img->generate_mipmaps(); } if (tex.texture.is_null()) { - tex.texture.instantiate(); - tex.texture->create_from_image(img); + tex.texture = ImageTexture::create_from_image(img); } else { tex.texture->update(img); } @@ -2705,7 +2701,7 @@ RID TextServerAdvanced::font_get_glyph_texture_rid(const RID &p_font_rid, const } Size2 TextServerAdvanced::font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Size2()); MutexLock lock(fd->mutex); @@ -2730,8 +2726,7 @@ Size2 TextServerAdvanced::font_get_glyph_texture_size(const RID &p_font_rid, con img->generate_mipmaps(); } if (tex.texture.is_null()) { - tex.texture.instantiate(); - tex.texture->create_from_image(img); + tex.texture = ImageTexture::create_from_image(img); } else { tex.texture->update(img); } @@ -2745,7 +2740,7 @@ Size2 TextServerAdvanced::font_get_glyph_texture_size(const RID &p_font_rid, con } Dictionary TextServerAdvanced::font_get_glyph_contours(const RID &p_font_rid, int64_t p_size, int64_t p_index) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Dictionary()); MutexLock lock(fd->mutex); @@ -2795,7 +2790,7 @@ Dictionary TextServerAdvanced::font_get_glyph_contours(const RID &p_font_rid, in } Array TextServerAdvanced::font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Array()); MutexLock lock(fd->mutex); @@ -2804,14 +2799,14 @@ Array TextServerAdvanced::font_get_kerning_list(const RID &p_font_rid, int64_t p ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Array()); Array ret; - for (const KeyValue<Vector2i, FontDataForSizeAdvanced *> &E : fd->cache) { + for (const KeyValue<Vector2i, FontForSizeAdvanced *> &E : fd->cache) { ret.push_back(E.key); } return ret; } void TextServerAdvanced::font_clear_kerning_map(const RID &p_font_rid, int64_t p_size) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2822,7 +2817,7 @@ void TextServerAdvanced::font_clear_kerning_map(const RID &p_font_rid, int64_t p } void TextServerAdvanced::font_remove_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2833,7 +2828,7 @@ void TextServerAdvanced::font_remove_kerning(const RID &p_font_rid, int64_t p_si } void TextServerAdvanced::font_set_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2844,7 +2839,7 @@ void TextServerAdvanced::font_set_kerning(const RID &p_font_rid, int64_t p_size, } Vector2 TextServerAdvanced::font_get_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Vector2()); MutexLock lock(fd->mutex); @@ -2877,7 +2872,7 @@ Vector2 TextServerAdvanced::font_get_kerning(const RID &p_font_rid, int64_t p_si } int64_t TextServerAdvanced::font_get_glyph_index(const RID &p_font_rid, int64_t p_size, int64_t p_char, int64_t p_variation_selector) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0); ERR_FAIL_COND_V_MSG((p_char >= 0xd800 && p_char <= 0xdfff) || (p_char > 0x10ffff), 0, "Unicode parsing error: Invalid unicode codepoint " + String::num_int64(p_char, 16) + "."); ERR_FAIL_COND_V_MSG((p_variation_selector >= 0xd800 && p_variation_selector <= 0xdfff) || (p_variation_selector > 0x10ffff), 0, "Unicode parsing error: Invalid unicode codepoint " + String::num_int64(p_variation_selector, 16) + "."); @@ -2902,7 +2897,7 @@ int64_t TextServerAdvanced::font_get_glyph_index(const RID &p_font_rid, int64_t } bool TextServerAdvanced::font_has_char(const RID &p_font_rid, int64_t p_char) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); ERR_FAIL_COND_V_MSG((p_char >= 0xd800 && p_char <= 0xdfff) || (p_char > 0x10ffff), false, "Unicode parsing error: Invalid unicode codepoint " + String::num_int64(p_char, 16) + "."); @@ -2910,7 +2905,7 @@ bool TextServerAdvanced::font_has_char(const RID &p_font_rid, int64_t p_char) co if (fd->cache.is_empty()) { ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, fd->msdf ? Vector2i(fd->msdf_source_size, 0) : Vector2i(16, 0)), false); } - FontDataForSizeAdvanced *at_size = fd->cache.begin()->value; + FontForSizeAdvanced *at_size = fd->cache.begin()->value; #ifdef MODULE_FREETYPE_ENABLED if (at_size && at_size->face) { @@ -2921,14 +2916,14 @@ bool TextServerAdvanced::font_has_char(const RID &p_font_rid, int64_t p_char) co } String TextServerAdvanced::font_get_supported_chars(const RID &p_font_rid) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, String()); MutexLock lock(fd->mutex); if (fd->cache.is_empty()) { ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, fd->msdf ? Vector2i(fd->msdf_source_size, 0) : Vector2i(16, 0)), String()); } - FontDataForSizeAdvanced *at_size = fd->cache.begin()->value; + FontForSizeAdvanced *at_size = fd->cache.begin()->value; String chars; #ifdef MODULE_FREETYPE_ENABLED @@ -2954,7 +2949,7 @@ String TextServerAdvanced::font_get_supported_chars(const RID &p_font_rid) const } void TextServerAdvanced::font_render_range(const RID &p_font_rid, const Vector2i &p_size, int64_t p_start, int64_t p_end) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); ERR_FAIL_COND_MSG((p_start >= 0xd800 && p_start <= 0xdfff) || (p_start > 0x10ffff), "Unicode parsing error: Invalid unicode codepoint " + String::num_int64(p_start, 16) + "."); ERR_FAIL_COND_MSG((p_end >= 0xd800 && p_end <= 0xdfff) || (p_end > 0x10ffff), "Unicode parsing error: Invalid unicode codepoint " + String::num_int64(p_end, 16) + "."); @@ -2987,7 +2982,7 @@ void TextServerAdvanced::font_render_range(const RID &p_font_rid, const Vector2i } void TextServerAdvanced::font_render_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_index) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -3016,7 +3011,7 @@ void TextServerAdvanced::font_render_glyph(const RID &p_font_rid, const Vector2i } void TextServerAdvanced::font_draw_glyph(const RID &p_font_rid, const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -3062,8 +3057,7 @@ void TextServerAdvanced::font_draw_glyph(const RID &p_font_rid, const RID &p_can img->generate_mipmaps(); } if (tex.texture.is_null()) { - tex.texture.instantiate(); - tex.texture->create_from_image(img); + tex.texture = ImageTexture::create_from_image(img); } else { tex.texture->update(img); } @@ -3095,7 +3089,7 @@ void TextServerAdvanced::font_draw_glyph(const RID &p_font_rid, const RID &p_can } void TextServerAdvanced::font_draw_glyph_outline(const RID &p_font_rid, const RID &p_canvas, int64_t p_size, int64_t p_outline_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -3141,8 +3135,7 @@ void TextServerAdvanced::font_draw_glyph_outline(const RID &p_font_rid, const RI img->generate_mipmaps(); } if (tex.texture.is_null()) { - tex.texture.instantiate(); - tex.texture->create_from_image(img); + tex.texture = ImageTexture::create_from_image(img); } else { tex.texture->update(img); } @@ -3174,7 +3167,7 @@ void TextServerAdvanced::font_draw_glyph_outline(const RID &p_font_rid, const RI } bool TextServerAdvanced::font_is_language_supported(const RID &p_font_rid, const String &p_language) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -3186,7 +3179,7 @@ bool TextServerAdvanced::font_is_language_supported(const RID &p_font_rid, const } void TextServerAdvanced::font_set_language_support_override(const RID &p_font_rid, const String &p_language, bool p_supported) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -3194,7 +3187,7 @@ void TextServerAdvanced::font_set_language_support_override(const RID &p_font_ri } bool TextServerAdvanced::font_get_language_support_override(const RID &p_font_rid, const String &p_language) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -3202,7 +3195,7 @@ bool TextServerAdvanced::font_get_language_support_override(const RID &p_font_ri } void TextServerAdvanced::font_remove_language_support_override(const RID &p_font_rid, const String &p_language) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -3210,7 +3203,7 @@ void TextServerAdvanced::font_remove_language_support_override(const RID &p_font } PackedStringArray TextServerAdvanced::font_get_language_support_overrides(const RID &p_font_rid) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, PackedStringArray()); MutexLock lock(fd->mutex); @@ -3222,7 +3215,7 @@ PackedStringArray TextServerAdvanced::font_get_language_support_overrides(const } bool TextServerAdvanced::font_is_script_supported(const RID &p_font_rid, const String &p_script) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -3236,7 +3229,7 @@ bool TextServerAdvanced::font_is_script_supported(const RID &p_font_rid, const S } void TextServerAdvanced::font_set_script_support_override(const RID &p_font_rid, const String &p_script, bool p_supported) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -3244,7 +3237,7 @@ void TextServerAdvanced::font_set_script_support_override(const RID &p_font_rid, } bool TextServerAdvanced::font_get_script_support_override(const RID &p_font_rid, const String &p_script) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -3252,7 +3245,7 @@ bool TextServerAdvanced::font_get_script_support_override(const RID &p_font_rid, } void TextServerAdvanced::font_remove_script_support_override(const RID &p_font_rid, const String &p_script) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -3260,7 +3253,7 @@ void TextServerAdvanced::font_remove_script_support_override(const RID &p_font_r } PackedStringArray TextServerAdvanced::font_get_script_support_overrides(const RID &p_font_rid) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, PackedStringArray()); MutexLock lock(fd->mutex); @@ -3272,7 +3265,7 @@ PackedStringArray TextServerAdvanced::font_get_script_support_overrides(const RI } void TextServerAdvanced::font_set_opentype_feature_overrides(const RID &p_font_rid, const Dictionary &p_overrides) { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -3282,7 +3275,7 @@ void TextServerAdvanced::font_set_opentype_feature_overrides(const RID &p_font_r } Dictionary TextServerAdvanced::font_get_opentype_feature_overrides(const RID &p_font_rid) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Dictionary()); MutexLock lock(fd->mutex); @@ -3290,7 +3283,7 @@ Dictionary TextServerAdvanced::font_get_opentype_feature_overrides(const RID &p_ } Dictionary TextServerAdvanced::font_supported_feature_list(const RID &p_font_rid) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Dictionary()); MutexLock lock(fd->mutex); @@ -3300,7 +3293,7 @@ Dictionary TextServerAdvanced::font_supported_feature_list(const RID &p_font_rid } Dictionary TextServerAdvanced::font_supported_variation_list(const RID &p_font_rid) const { - FontDataAdvanced *fd = font_owner.get_or_null(p_font_rid); + FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Dictionary()); MutexLock lock(fd->mutex); @@ -3580,6 +3573,31 @@ bool TextServerAdvanced::shaped_text_get_preserve_control(const RID &p_shaped) c return sd->preserve_control; } +void TextServerAdvanced::shaped_text_set_spacing(const RID &p_shaped, SpacingType p_spacing, int64_t p_value) { + ERR_FAIL_INDEX((int)p_spacing, 4); + ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND(!sd); + + MutexLock lock(sd->mutex); + if (sd->extra_spacing[p_spacing] != p_value) { + if (sd->parent != RID()) { + full_copy(sd); + } + sd->extra_spacing[p_spacing] = p_value; + invalidate(sd, false); + } +} + +int64_t TextServerAdvanced::shaped_text_get_spacing(const RID &p_shaped, SpacingType p_spacing) const { + ERR_FAIL_INDEX_V((int)p_spacing, 4, 0); + + const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND_V(!sd, 0); + + MutexLock lock(sd->mutex); + return sd->extra_spacing[p_spacing]; +} + TextServer::Orientation TextServerAdvanced::shaped_text_get_orientation(const RID &p_shaped) const { const ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, TextServer::ORIENTATION_HORIZONTAL); @@ -3847,6 +3865,9 @@ RID TextServerAdvanced::shaped_text_substr(const RID &p_shaped, int64_t p_start, new_sd->direction = sd->direction; new_sd->custom_punct = sd->custom_punct; new_sd->para_direction = sd->para_direction; + for (int i = 0; i < TextServer::SPACING_MAX; i++) { + new_sd->extra_spacing[i] = sd->extra_spacing[i]; + } if (!_shape_substr(new_sd, sd, p_start, p_length)) { memdelete(new_sd); @@ -3972,7 +3993,7 @@ RID TextServerAdvanced::shaped_text_get_parent(const RID &p_shaped) const { return sd->parent; } -double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t /*JustificationFlag*/ p_jst_flags) { +double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double p_width, BitField<TextServer::JustificationFlag> p_jst_flags) { ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, 0.0); @@ -3988,7 +4009,7 @@ double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double int start_pos = 0; int end_pos = sd->glyphs.size() - 1; - if ((p_jst_flags & JUSTIFICATION_AFTER_LAST_TAB) == JUSTIFICATION_AFTER_LAST_TAB) { + if (p_jst_flags.has_flag(JUSTIFICATION_AFTER_LAST_TAB)) { int start, end, delta; if (sd->para_direction == DIRECTION_LTR) { start = sd->glyphs.size() - 1; @@ -4014,7 +4035,7 @@ double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double } double justification_width; - if ((p_jst_flags & JUSTIFICATION_CONSTRAIN_ELLIPSIS) == JUSTIFICATION_CONSTRAIN_ELLIPSIS) { + if (p_jst_flags.has_flag(JUSTIFICATION_CONSTRAIN_ELLIPSIS)) { if (sd->overrun_trim_data.trim_pos >= 0) { if (sd->para_direction == DIRECTION_RTL) { start_pos = sd->overrun_trim_data.trim_pos; @@ -4029,7 +4050,7 @@ double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double justification_width = sd->width; } - if ((p_jst_flags & JUSTIFICATION_TRIM_EDGE_SPACES) == JUSTIFICATION_TRIM_EDGE_SPACES) { + if (p_jst_flags.has_flag(JUSTIFICATION_TRIM_EDGE_SPACES)) { // Trim spaces. while ((start_pos < end_pos) && ((sd->glyphs[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (sd->glyphs[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (sd->glyphs[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) { justification_width -= sd->glyphs[start_pos].advance * sd->glyphs[start_pos].repeat; @@ -4068,7 +4089,7 @@ double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double } } - if ((elongation_count > 0) && ((p_jst_flags & JUSTIFICATION_KASHIDA) == JUSTIFICATION_KASHIDA)) { + if ((elongation_count > 0) && p_jst_flags.has_flag(JUSTIFICATION_KASHIDA)) { double delta_width_per_kashida = (p_width - justification_width) / elongation_count; for (int i = start_pos; i <= end_pos; i++) { Glyph &gl = sd->glyphs.write[i]; @@ -4089,7 +4110,7 @@ double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double } } } - if ((space_count > 0) && ((p_jst_flags & JUSTIFICATION_WORD_BOUND) == JUSTIFICATION_WORD_BOUND)) { + if ((space_count > 0) && p_jst_flags.has_flag(JUSTIFICATION_WORD_BOUND)) { double delta_width_per_space = (p_width - justification_width) / space_count; double adv_remain = 0; for (int i = start_pos; i <= end_pos; i++) { @@ -4122,7 +4143,7 @@ double TextServerAdvanced::shaped_text_fit_to_width(const RID &p_shaped, double sd->fit_width_minimum_reached = true; } - if ((p_jst_flags & JUSTIFICATION_CONSTRAIN_ELLIPSIS) != JUSTIFICATION_CONSTRAIN_ELLIPSIS) { + if (!p_jst_flags.has_flag(JUSTIFICATION_CONSTRAIN_ELLIPSIS)) { sd->width = justification_width; } @@ -4185,7 +4206,7 @@ double TextServerAdvanced::shaped_text_tab_align(const RID &p_shaped, const Pack return 0.0; } -void TextServerAdvanced::shaped_text_overrun_trim_to_width(const RID &p_shaped_line, double p_width, int64_t p_trim_flags) { +void TextServerAdvanced::shaped_text_overrun_trim_to_width(const RID &p_shaped_line, double p_width, BitField<TextServer::TextOverrunFlag> p_trim_flags) { ShapedTextDataAdvanced *sd = shaped_owner.get_or_null(p_shaped_line); ERR_FAIL_COND_MSG(!sd, "ShapedTextDataAdvanced invalid."); @@ -4197,14 +4218,14 @@ void TextServerAdvanced::shaped_text_overrun_trim_to_width(const RID &p_shaped_l sd->text_trimmed = false; sd->overrun_trim_data.ellipsis_glyph_buf.clear(); - bool add_ellipsis = (p_trim_flags & OVERRUN_ADD_ELLIPSIS) == OVERRUN_ADD_ELLIPSIS; - bool cut_per_word = (p_trim_flags & OVERRUN_TRIM_WORD_ONLY) == OVERRUN_TRIM_WORD_ONLY; - bool enforce_ellipsis = (p_trim_flags & OVERRUN_ENFORCE_ELLIPSIS) == OVERRUN_ENFORCE_ELLIPSIS; - bool justification_aware = (p_trim_flags & OVERRUN_JUSTIFICATION_AWARE) == OVERRUN_JUSTIFICATION_AWARE; + bool add_ellipsis = p_trim_flags.has_flag(OVERRUN_ADD_ELLIPSIS); + bool cut_per_word = p_trim_flags.has_flag(OVERRUN_TRIM_WORD_ONLY); + bool enforce_ellipsis = p_trim_flags.has_flag(OVERRUN_ENFORCE_ELLIPSIS); + bool justification_aware = p_trim_flags.has_flag(OVERRUN_JUSTIFICATION_AWARE); Glyph *sd_glyphs = sd->glyphs.ptrw(); - if ((p_trim_flags & OVERRUN_TRIM) == OVERRUN_NO_TRIM || sd_glyphs == nullptr || p_width <= 0 || !(sd->width > p_width || enforce_ellipsis)) { + if (p_trim_flags.has_flag(OVERRUN_TRIM) || sd_glyphs == nullptr || p_width <= 0 || !(sd->width > p_width || enforce_ellipsis)) { sd->overrun_trim_data.trim_pos = -1; sd->overrun_trim_data.ellipsis_pos = -1; return; @@ -4257,7 +4278,7 @@ void TextServerAdvanced::shaped_text_overrun_trim_to_width(const RID &p_shaped_l int ellipsis_width = 0; if (add_ellipsis && whitespace_gl_font_rid.is_valid()) { - ellipsis_width = 3 * dot_adv.x + font_get_spacing(whitespace_gl_font_rid, last_gl_font_size, SPACING_GLYPH) + (cut_per_word ? whitespace_adv.x : 0); + ellipsis_width = 3 * dot_adv.x + sd->extra_spacing[SPACING_GLYPH] + (cut_per_word ? whitespace_adv.x : 0); } int ell_min_characters = 6; @@ -4405,7 +4426,7 @@ bool TextServerAdvanced::shaped_text_update_breaks(const RID &p_shaped) { i++; } int r_end = sd->spans[i].end; - UBreakIterator *bi = ubrk_open(UBRK_LINE, language.ascii().get_data(), data + _convert_pos_inv(sd, r_start), _convert_pos_inv(sd, r_end - r_start), &err); + UBreakIterator *bi = ubrk_open(UBRK_LINE, (language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale().ascii().get_data() : language.ascii().get_data(), data + _convert_pos_inv(sd, r_start), _convert_pos_inv(sd, r_end - r_start), &err); if (U_FAILURE(err)) { // No data loaded - use fallback. for (int j = r_start; j < r_end; j++) { @@ -4851,15 +4872,16 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star } RID f = p_fonts[p_fb_index]; - FontDataAdvanced *fd = font_owner.get_or_null(f); + FontAdvanced *fd = font_owner.get_or_null(f); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); Vector2i fss = _get_size(fd, fs); hb_font_t *hb_font = _font_get_hb_handle(f, fs); double scale = font_get_scale(f, fs); - double sp_sp = font_get_spacing(f, fs, SPACING_SPACE); - double sp_gl = font_get_spacing(f, fs, SPACING_GLYPH); + double sp_sp = p_sd->extra_spacing[SPACING_SPACE]; + double sp_gl = p_sd->extra_spacing[SPACING_GLYPH]; + bool last_run = (p_sd->end == p_end); double ea = _get_extra_advance(f, fs); bool subpos = (font_get_subpixel_positioning(f) == SUBPIXEL_POSITIONING_ONE_HALF) || (font_get_subpixel_positioning(f) == SUBPIXEL_POSITIONING_ONE_QUARTER) || (font_get_subpixel_positioning(f) == SUBPIXEL_POSITIONING_AUTO && fs <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE); ERR_FAIL_COND(hb_font == nullptr); @@ -4873,7 +4895,10 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star } hb_buffer_set_script(p_sd->hb_buffer, p_script); - if (!p_sd->spans[p_span].language.is_empty()) { + if (p_sd->spans[p_span].language.is_empty()) { + hb_language_t lang = hb_language_from_string(TranslationServer::get_singleton()->get_tool_locale().ascii().get_data(), -1); + hb_buffer_set_language(p_sd->hb_buffer, lang); + } else { hb_language_t lang = hb_language_from_string(p_sd->spans[p_span].language.ascii().get_data(), -1); hb_buffer_set_language(p_sd->hb_buffer, lang); } @@ -4954,10 +4979,13 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star } gl.y_off = -Math::round(glyph_pos[i].y_offset / (64.0 / scale)); } - if (sp_sp && is_whitespace(p_sd->text[glyph_info[i].cluster])) { - gl.advance += sp_sp; - } else { - gl.advance += sp_gl; + if (!last_run || i < glyph_count - 1) { + // Do not add extra spacing to the last glyph of the string. + if (sp_sp && is_whitespace(p_sd->text[glyph_info[i].cluster])) { + gl.advance += sp_sp; + } else { + gl.advance += sp_gl; + } } if (p_sd->preserve_control) { @@ -5288,9 +5316,9 @@ Size2 TextServerAdvanced::shaped_text_get_size(const RID &p_shaped) const { const_cast<TextServerAdvanced *>(this)->shaped_text_shape(p_shaped); } if (sd->orientation == TextServer::ORIENTATION_HORIZONTAL) { - return Size2((sd->text_trimmed ? sd->width_trimmed : sd->width), sd->ascent + sd->descent).ceil(); + return Size2((sd->text_trimmed ? sd->width_trimmed : sd->width), sd->ascent + sd->descent + sd->extra_spacing[SPACING_TOP] + sd->extra_spacing[SPACING_BOTTOM]).ceil(); } else { - return Size2(sd->ascent + sd->descent, (sd->text_trimmed ? sd->width_trimmed : sd->width)).ceil(); + return Size2(sd->ascent + sd->descent + sd->extra_spacing[SPACING_TOP] + sd->extra_spacing[SPACING_BOTTOM], (sd->text_trimmed ? sd->width_trimmed : sd->width)).ceil(); } } @@ -5302,7 +5330,7 @@ double TextServerAdvanced::shaped_text_get_ascent(const RID &p_shaped) const { if (!sd->valid) { const_cast<TextServerAdvanced *>(this)->shaped_text_shape(p_shaped); } - return sd->ascent; + return sd->ascent + sd->extra_spacing[SPACING_TOP]; } double TextServerAdvanced::shaped_text_get_descent(const RID &p_shaped) const { @@ -5313,7 +5341,7 @@ double TextServerAdvanced::shaped_text_get_descent(const RID &p_shaped) const { if (!sd->valid) { const_cast<TextServerAdvanced *>(this)->shaped_text_shape(p_shaped); } - return sd->descent; + return sd->descent + sd->extra_spacing[SPACING_BOTTOM]; } double TextServerAdvanced::shaped_text_get_width(const RID &p_shaped) const { @@ -5627,16 +5655,18 @@ String TextServerAdvanced::strip_diacritics(const String &p_string) const { } String TextServerAdvanced::string_to_upper(const String &p_string, const String &p_language) const { + const String lang = (p_language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale() : p_language; + // Convert to UTF-16. Char16String utf16 = p_string.utf16(); Vector<char16_t> upper; UErrorCode err = U_ZERO_ERROR; - int32_t len = u_strToUpper(nullptr, 0, utf16.get_data(), -1, p_language.ascii().get_data(), &err); + int32_t len = u_strToUpper(nullptr, 0, utf16.get_data(), -1, lang.ascii().get_data(), &err); ERR_FAIL_COND_V_MSG(err != U_BUFFER_OVERFLOW_ERROR, p_string, u_errorName(err)); upper.resize(len); err = U_ZERO_ERROR; - u_strToUpper(upper.ptrw(), len, utf16.get_data(), -1, p_language.ascii().get_data(), &err); + u_strToUpper(upper.ptrw(), len, utf16.get_data(), -1, lang.ascii().get_data(), &err); ERR_FAIL_COND_V_MSG(U_FAILURE(err), p_string, u_errorName(err)); // Convert back to UTF-32. @@ -5644,16 +5674,17 @@ String TextServerAdvanced::string_to_upper(const String &p_string, const String } String TextServerAdvanced::string_to_lower(const String &p_string, const String &p_language) const { + const String lang = (p_language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale() : p_language; // Convert to UTF-16. Char16String utf16 = p_string.utf16(); Vector<char16_t> lower; UErrorCode err = U_ZERO_ERROR; - int32_t len = u_strToLower(nullptr, 0, utf16.get_data(), -1, p_language.ascii().get_data(), &err); + int32_t len = u_strToLower(nullptr, 0, utf16.get_data(), -1, lang.ascii().get_data(), &err); ERR_FAIL_COND_V_MSG(err != U_BUFFER_OVERFLOW_ERROR, p_string, u_errorName(err)); lower.resize(len); err = U_ZERO_ERROR; - u_strToLower(lower.ptrw(), len, utf16.get_data(), -1, p_language.ascii().get_data(), &err); + u_strToLower(lower.ptrw(), len, utf16.get_data(), -1, lang.ascii().get_data(), &err); ERR_FAIL_COND_V_MSG(U_FAILURE(err), p_string, u_errorName(err)); // Convert back to UTF-32. @@ -5661,12 +5692,13 @@ String TextServerAdvanced::string_to_lower(const String &p_string, const String } PackedInt32Array TextServerAdvanced::string_get_word_breaks(const String &p_string, const String &p_language) const { + const String lang = (p_language.is_empty()) ? TranslationServer::get_singleton()->get_tool_locale() : p_language; // Convert to UTF-16. Char16String utf16 = p_string.utf16(); HashSet<int> breaks; UErrorCode err = U_ZERO_ERROR; - UBreakIterator *bi = ubrk_open(UBRK_LINE, p_language.ascii().get_data(), (const UChar *)utf16.get_data(), utf16.length(), &err); + UBreakIterator *bi = ubrk_open(UBRK_LINE, lang.ascii().get_data(), (const UChar *)utf16.get_data(), utf16.length(), &err); if (U_FAILURE(err)) { // No data loaded - use fallback. for (int i = 0; i < p_string.length(); i++) { diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h index e7690cb70d..8cd0e753ba 100644 --- a/modules/text_server_adv/text_server_adv.h +++ b/modules/text_server_adv/text_server_adv.h @@ -65,11 +65,12 @@ #include <godot_cpp/classes/image.hpp> #include <godot_cpp/classes/image_texture.hpp> #include <godot_cpp/classes/ref.hpp> +#include <godot_cpp/classes/worker_thread_pool.hpp> #include <godot_cpp/templates/hash_map.hpp> #include <godot_cpp/templates/hash_set.hpp> #include <godot_cpp/templates/rid_owner.hpp> -#include <godot_cpp/templates/thread_work_pool.hpp> + #include <godot_cpp/templates/vector.hpp> using namespace godot; @@ -77,9 +78,9 @@ using namespace godot; #else // Headers for building as built-in module. +#include "core/object/worker_thread_pool.h" #include "core/templates/hash_map.h" #include "core/templates/rid_owner.h" -#include "core/templates/thread_work_pool.h" #include "scene/resources/texture.h" #include "servers/text/text_server_extension.h" @@ -133,12 +134,19 @@ class TextServerAdvanced : public TextServerExtension { }; Vector<NumSystemData> num_systems; + + struct FeatureInfo { + StringName name; + Variant::Type vtype = Variant::INT; + bool hidden = false; + }; + HashMap<StringName, int32_t> feature_sets; - HashMap<int32_t, StringName> feature_sets_inv; + HashMap<int32_t, FeatureInfo> feature_sets_inv; void _insert_num_systems_lang(); void _insert_feature_sets(); - _FORCE_INLINE_ void _insert_feature(const StringName &p_name, int32_t p_tag); + _FORCE_INLINE_ void _insert_feature(const StringName &p_name, int32_t p_tag, Variant::Type p_vtype = Variant::INT, bool p_hidden = false); // ICU support data. @@ -176,7 +184,7 @@ class TextServerAdvanced : public TextServerExtension { Vector2 advance; }; - struct FontDataForSizeAdvanced { + struct FontForSizeAdvanced { double ascent = 0.0; double descent = 0.0; double underline_position = 0.0; @@ -184,9 +192,6 @@ class TextServerAdvanced : public TextServerExtension { double scale = 1.0; double oversampling = 1.0; - int spacing_glyph = 0; - int spacing_space = 0; - Vector2i size; Vector<FontTexture> textures; @@ -199,7 +204,7 @@ class TextServerAdvanced : public TextServerExtension { FT_StreamRec stream; #endif - ~FontDataForSizeAdvanced() { + ~FontForSizeAdvanced() { if (hb_handle != nullptr) { hb_font_destroy(hb_handle); } @@ -211,7 +216,7 @@ class TextServerAdvanced : public TextServerExtension { } }; - struct FontDataAdvanced { + struct FontAdvanced { Mutex mutex; bool antialiased = true; @@ -228,11 +233,11 @@ class TextServerAdvanced : public TextServerExtension { double embolden = 0.0; Transform2D transform; - uint32_t style_flags = 0; + BitField<TextServer::FontStyle> style_flags = 0; String font_name; String style_name; - HashMap<Vector2i, FontDataForSizeAdvanced *, VariantHasher, VariantComparator> cache; + HashMap<Vector2i, FontForSizeAdvanced *, VariantHasher, VariantComparator> cache; bool face_init = false; HashSet<uint32_t> supported_scripts; @@ -248,30 +253,28 @@ class TextServerAdvanced : public TextServerExtension { const uint8_t *data_ptr; size_t data_size; int face_index = 0; - mutable ThreadWorkPool work_pool; - ~FontDataAdvanced() { - work_pool.finish(); - for (const KeyValue<Vector2i, FontDataForSizeAdvanced *> &E : cache) { + ~FontAdvanced() { + for (const KeyValue<Vector2i, FontForSizeAdvanced *> &E : cache) { memdelete(E.value); } cache.clear(); } }; - _FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontDataForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const; + _FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontForSizeAdvanced *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const; #ifdef MODULE_MSDFGEN_ENABLED - _FORCE_INLINE_ FontGlyph rasterize_msdf(FontDataAdvanced *p_font_data, FontDataForSizeAdvanced *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const; + _FORCE_INLINE_ FontGlyph rasterize_msdf(FontAdvanced *p_font_data, FontForSizeAdvanced *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const; #endif #ifdef MODULE_FREETYPE_ENABLED - _FORCE_INLINE_ FontGlyph rasterize_bitmap(FontDataForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const; + _FORCE_INLINE_ FontGlyph rasterize_bitmap(FontForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const; #endif - _FORCE_INLINE_ bool _ensure_glyph(FontDataAdvanced *p_font_data, const Vector2i &p_size, int32_t p_glyph) const; - _FORCE_INLINE_ bool _ensure_cache_for_size(FontDataAdvanced *p_font_data, const Vector2i &p_size) const; - _FORCE_INLINE_ void _font_clear_cache(FontDataAdvanced *p_font_data); + _FORCE_INLINE_ bool _ensure_glyph(FontAdvanced *p_font_data, const Vector2i &p_size, int32_t p_glyph) const; + _FORCE_INLINE_ bool _ensure_cache_for_size(FontAdvanced *p_font_data, const Vector2i &p_size) const; + _FORCE_INLINE_ void _font_clear_cache(FontAdvanced *p_font_data); void _generateMTSDF_threaded(uint32_t y, void *p_td) const; - _FORCE_INLINE_ Vector2i _get_size(const FontDataAdvanced *p_font_data, int p_size) const { + _FORCE_INLINE_ Vector2i _get_size(const FontAdvanced *p_font_data, int p_size) const { if (p_font_data->msdf) { return Vector2i(p_font_data->msdf_source_size, 0); } else if (p_font_data->fixed_size > 0) { @@ -281,7 +284,7 @@ class TextServerAdvanced : public TextServerExtension { } } - _FORCE_INLINE_ Vector2i _get_size_outline(const FontDataAdvanced *p_font_data, const Vector2i &p_size) const { + _FORCE_INLINE_ Vector2i _get_size_outline(const FontAdvanced *p_font_data, const Vector2i &p_size) const { if (p_font_data->msdf) { return Vector2i(p_font_data->msdf_source_size, 0); } else if (p_font_data->fixed_size > 0) { @@ -292,6 +295,8 @@ class TextServerAdvanced : public TextServerExtension { } _FORCE_INLINE_ double _get_extra_advance(RID p_font_rid, int p_font_size) const; + _FORCE_INLINE_ Variant::Type _get_tag_type(int64_t p_tag) const; + _FORCE_INLINE_ bool _get_tag_hidden(int64_t p_tag) const; // Shaped text cache data. struct TrimData { @@ -351,6 +356,7 @@ class TextServerAdvanced : public TextServerExtension { double descent = 0.0; // Descent for horizontal layout, 1/2 of width for vertical. double width = 0.0; // Width for horizontal layout, height for vertical. double width_trimmed = 0.0; + int extra_spacing[4] = { 0, 0, 0, 0 }; double upos = 0.0; double uthk = 0.0; @@ -389,7 +395,7 @@ class TextServerAdvanced : public TextServerExtension { // Common data. double oversampling = 1.0; - mutable RID_PtrOwner<FontDataAdvanced> font_owner; + mutable RID_PtrOwner<FontAdvanced> font_owner; mutable RID_PtrOwner<ShapedTextDataAdvanced> shaped_owner; void _realign(ShapedTextDataAdvanced *p_sd) const; @@ -407,11 +413,11 @@ class TextServerAdvanced : public TextServerExtension { static hb_font_funcs_t *funcs; struct bmp_font_t { - TextServerAdvanced::FontDataForSizeAdvanced *face = nullptr; + TextServerAdvanced::FontForSizeAdvanced *face = nullptr; bool unref = false; /* Whether to destroy bm_face when done. */ }; - static bmp_font_t *_bmp_font_create(TextServerAdvanced::FontDataForSizeAdvanced *p_face, bool p_unref); + static bmp_font_t *_bmp_font_create(TextServerAdvanced::FontForSizeAdvanced *p_face, bool p_unref); static void _bmp_font_destroy(void *p_data); static hb_bool_t _bmp_get_nominal_glyph(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_unicode, hb_codepoint_t *r_glyph, void *p_user_data); static hb_position_t _bmp_get_glyph_h_advance(hb_font_t *p_font, void *p_font_data, hb_codepoint_t p_glyph, void *p_user_data); @@ -422,8 +428,8 @@ class TextServerAdvanced : public TextServerExtension { static hb_bool_t _bmp_get_font_h_extents(hb_font_t *p_font, void *p_font_data, hb_font_extents_t *r_metrics, void *p_user_data); static void _bmp_create_font_funcs(); static void _bmp_free_font_funcs(); - static void _bmp_font_set_funcs(hb_font_t *p_font, TextServerAdvanced::FontDataForSizeAdvanced *p_face, bool p_unref); - static hb_font_t *_bmp_font_create(TextServerAdvanced::FontDataForSizeAdvanced *p_face, hb_destroy_func_t p_destroy); + static void _bmp_font_set_funcs(hb_font_t *p_font, TextServerAdvanced::FontForSizeAdvanced *p_face, bool p_unref); + static hb_font_t *_bmp_font_create(TextServerAdvanced::FontForSizeAdvanced *p_face, hb_destroy_func_t p_destroy); hb_font_t *_font_get_hb_handle(const RID &p_font, int64_t p_font_size) const; @@ -479,8 +485,8 @@ public: virtual int64_t font_get_face_count(const RID &p_font_rid) const override; - virtual void font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) override; - virtual int64_t /*FontStyle*/ font_get_style(const RID &p_font_rid) const override; + virtual void font_set_style(const RID &p_font_rid, BitField<FontStyle> p_style) override; + virtual BitField<FontStyle> font_get_style(const RID &p_font_rid) const override; virtual void font_set_style_name(const RID &p_font_rid, const String &p_name) override; virtual String font_get_style_name(const RID &p_font_rid) const override; @@ -546,9 +552,6 @@ public: virtual void font_set_scale(const RID &p_font_rid, int64_t p_size, double p_scale) override; virtual double font_get_scale(const RID &p_font_rid, int64_t p_size) const override; - virtual void font_set_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing, int64_t p_value) override; - virtual int64_t font_get_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing) const override; - virtual int64_t font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const override; virtual void font_clear_textures(const RID &p_font_rid, const Vector2i &p_size) override; virtual void font_remove_texture(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) override; @@ -646,6 +649,9 @@ public: virtual void shaped_text_set_preserve_control(const RID &p_shaped, bool p_enabled) override; virtual bool shaped_text_get_preserve_control(const RID &p_shaped) const override; + virtual void shaped_text_set_spacing(const RID &p_shaped, SpacingType p_spacing, int64_t p_value) override; + virtual int64_t shaped_text_get_spacing(const RID &p_shaped, SpacingType p_spacing) const override; + virtual bool shaped_text_add_string(const RID &p_shaped, const String &p_text, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) override; virtual bool shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int64_t p_length = 1) override; virtual bool shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER) override; @@ -657,7 +663,7 @@ public: virtual RID shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const override; virtual RID shaped_text_get_parent(const RID &p_shaped) const override; - virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override; + virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, BitField<TextServer::JustificationFlag> p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override; virtual double shaped_text_tab_align(const RID &p_shaped, const PackedFloat32Array &p_tab_stops) override; virtual bool shaped_text_shape(const RID &p_shaped) override; @@ -669,7 +675,7 @@ public: virtual const Glyph *shaped_text_get_ellipsis_glyphs(const RID &p_shaped) const override; virtual int64_t shaped_text_get_ellipsis_glyph_count(const RID &p_shaped) const override; - virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, int64_t p_trim_flags) override; + virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, BitField<TextServer::TextOverrunFlag> p_trim_flags) override; virtual bool shaped_text_is_ready(const RID &p_shaped) const override; diff --git a/modules/text_server_fb/gdextension_build/SConstruct b/modules/text_server_fb/gdextension_build/SConstruct index 6c9e10db18..de0a549900 100644 --- a/modules/text_server_fb/gdextension_build/SConstruct +++ b/modules/text_server_fb/gdextension_build/SConstruct @@ -184,15 +184,15 @@ env.Append(CPPDEFINES=["GDEXTENSION"]) env.Append(CPPPATH=["../"]) sources = Glob("../*.cpp") -if env["platform"] == "osx": - methods.write_osx_plist( - f'./bin/libtextserver_fallback.osx.{env["target"]}.framework', - f'libtextserver_fallback.osx.{env["target"]}', +if env["platform"] == "macos": + methods.write_macos_plist( + f'./bin/libtextserver_fallback.macos.{env["target"]}.framework', + f'libtextserver_fallback.macos.{env["target"]}', "org.godotengine.textserver_fallback", "Fallback Text Server", ) library = env.SharedLibrary( - f'./bin/libtextserver_fallback.osx.{env["target"]}.framework/libtextserver_fallback.osx.{env["target"]}', + f'./bin/libtextserver_fallback.macos.{env["target"]}.framework/libtextserver_fallback.macos.{env["target"]}', source=sources, ) else: diff --git a/modules/text_server_fb/gdextension_build/methods.py b/modules/text_server_fb/gdextension_build/methods.py index d404f2851e..3c5229462c 100644 --- a/modules/text_server_fb/gdextension_build/methods.py +++ b/modules/text_server_fb/gdextension_build/methods.py @@ -98,7 +98,7 @@ def make_icu_data(target, source, env): g.write("#endif") -def write_osx_plist(target, binary_name, identifier, name): +def write_macos_plist(target, binary_name, identifier, name): os.makedirs(f"{target}/Resourece/", exist_ok=True) f = open(f"{target}/Resourece/Info.plist", "w") diff --git a/modules/text_server_fb/gdextension_build/text_server_fb.gdextension b/modules/text_server_fb/gdextension_build/text_server_fb.gdextension index 1026c6cb85..9236555d63 100644 --- a/modules/text_server_fb/gdextension_build/text_server_fb.gdextension +++ b/modules/text_server_fb/gdextension_build/text_server_fb.gdextension @@ -8,5 +8,5 @@ linux.64.debug = "bin/libtextserver_fallback.linux.debug.64.so" linux.64.release = "bin/libtextserver_fallback.linux.release.64.so" windows.64.debug = "bin/libtextserver_fallback.windows.debug.64.dll" windows.64.release = "bin/libtextserver_fallback.windows.release.64.dll" -macos.debug = "bin/libtextserver_fallback.osx.debug.framework" -macos.release = "bin/libtextserver_fallback.osx.release.framework" +macos.debug = "bin/libtextserver_fallback.macos.debug.framework" +macos.release = "bin/libtextserver_fallback.macos.release.framework" diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp index f93c5909c9..50ea4677b1 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -104,7 +104,7 @@ int64_t TextServerFallback::get_features() const { void TextServerFallback::free_rid(const RID &p_rid) { _THREAD_SAFE_METHOD_ if (font_owner.owns(p_rid)) { - FontDataFallback *fd = font_owner.get_or_null(p_rid); + FontFallback *fd = font_owner.get_or_null(p_rid); font_owner.free(p_rid); memdelete(fd); } else if (shaped_owner.owns(p_rid)) { @@ -199,7 +199,7 @@ String TextServerFallback::tag_to_name(int64_t p_tag) const { /* Font Glyph Rendering */ /*************************************************************************/ -_FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_texture_pos_for_glyph(FontDataForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const { +_FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_texture_pos_for_glyph(FontForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const { FontTexturePosition ret; ret.index = -1; @@ -397,7 +397,7 @@ void TextServerFallback::_generateMTSDF_threaded(uint32_t y, void *p_td) const { } } -_FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf(FontDataFallback *p_font_data, FontDataForSizeFallback *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const { +_FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf(FontFallback *p_font_data, FontForSizeFallback *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const { msdfgen::Shape shape; shape.contours.clear(); @@ -461,10 +461,8 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf( td.projection = &projection; td.distancePixelConversion = &distancePixelConversion; - if (p_font_data->work_pool.get_thread_count() == 0) { - p_font_data->work_pool.init(); - } - p_font_data->work_pool.do_work(h, this, &TextServerFallback::_generateMTSDF_threaded, &td); + WorkerThreadPool::GroupID group_id = WorkerThreadPool::get_singleton()->add_template_group_task(this, &TextServerFallback::_generateMTSDF_threaded, &td, h, -1, true, SNAME("TextServerFBRenderMSDF")); + WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_id); msdfgen::msdfErrorCorrection(image, shape, projection, p_pixel_range, config); @@ -502,7 +500,7 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf( #endif #ifdef MODULE_FREETYPE_ENABLED -_FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitmap(FontDataForSizeFallback *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const { +_FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitmap(FontForSizeFallback *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const { int w = bitmap.width; int h = bitmap.rows; @@ -579,12 +577,12 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitma /* Font Cache */ /*************************************************************************/ -_FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontDataFallback *p_font_data, const Vector2i &p_size, int32_t p_glyph) const { +_FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontFallback *p_font_data, const Vector2i &p_size, int32_t p_glyph) const { ERR_FAIL_COND_V(!_ensure_cache_for_size(p_font_data, p_size), false); int32_t glyph_index = p_glyph & 0xffffff; // Remove subpixel shifts. - FontDataForSizeFallback *fd = p_font_data->cache[p_size]; + FontForSizeFallback *fd = p_font_data->cache[p_size]; if (fd->glyph_map.has(p_glyph)) { return fd->glyph_map[p_glyph].found; } @@ -705,13 +703,13 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontDataFallback *p_font_d return false; } -_FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontDataFallback *p_font_data, const Vector2i &p_size) const { +_FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontFallback *p_font_data, const Vector2i &p_size) const { ERR_FAIL_COND_V(p_size.x <= 0, false); if (p_font_data->cache.has(p_size)) { return true; } - FontDataForSizeFallback *fd = memnew(FontDataForSizeFallback); + FontForSizeFallback *fd = memnew(FontForSizeFallback); fd->size = p_size; if (p_font_data->data_ptr && (p_font_data->data_size > 0)) { // Init dynamic font. @@ -791,13 +789,13 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontDataFallback } p_font_data->style_flags = 0; if (fd->face->style_flags & FT_STYLE_FLAG_BOLD) { - p_font_data->style_flags |= FONT_BOLD; + p_font_data->style_flags.set_flag(FONT_BOLD); } if (fd->face->style_flags & FT_STYLE_FLAG_ITALIC) { - p_font_data->style_flags |= FONT_ITALIC; + p_font_data->style_flags.set_flag(FONT_ITALIC); } if (fd->face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) { - p_font_data->style_flags |= FONT_FIXED_WIDTH; + p_font_data->style_flags.set_flag(FONT_FIXED_WIDTH); } // Read OpenType variations. p_font_data->supported_varaitions.clear(); @@ -851,8 +849,8 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontDataFallback return true; } -_FORCE_INLINE_ void TextServerFallback::_font_clear_cache(FontDataFallback *p_font_data) { - for (const KeyValue<Vector2i, FontDataForSizeFallback *> &E : p_font_data->cache) { +_FORCE_INLINE_ void TextServerFallback::_font_clear_cache(FontFallback *p_font_data) { + for (const KeyValue<Vector2i, FontForSizeFallback *> &E : p_font_data->cache) { memdelete(E.value); } @@ -864,13 +862,13 @@ _FORCE_INLINE_ void TextServerFallback::_font_clear_cache(FontDataFallback *p_fo RID TextServerFallback::create_font() { _THREAD_SAFE_METHOD_ - FontDataFallback *fd = memnew(FontDataFallback); + FontFallback *fd = memnew(FontFallback); return font_owner.make_rid(fd); } void TextServerFallback::font_set_data(const RID &p_font_rid, const PackedByteArray &p_data) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -881,7 +879,7 @@ void TextServerFallback::font_set_data(const RID &p_font_rid, const PackedByteAr } void TextServerFallback::font_set_data_ptr(const RID &p_font_rid, const uint8_t *p_data_ptr, int64_t p_data_size) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -891,8 +889,8 @@ void TextServerFallback::font_set_data_ptr(const RID &p_font_rid, const uint8_t fd->data_size = p_data_size; } -void TextServerFallback::font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); +void TextServerFallback::font_set_style(const RID &p_font_rid, BitField<FontStyle> p_style) { + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -905,7 +903,7 @@ void TextServerFallback::font_set_face_index(const RID &p_font_rid, int64_t p_fa ERR_FAIL_COND(p_face_index < 0); ERR_FAIL_COND(p_face_index >= 0x7FFF); - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -916,7 +914,7 @@ void TextServerFallback::font_set_face_index(const RID &p_font_rid, int64_t p_fa } int64_t TextServerFallback::font_get_face_index(const RID &p_font_rid) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0); MutexLock lock(fd->mutex); @@ -924,7 +922,7 @@ int64_t TextServerFallback::font_get_face_index(const RID &p_font_rid) const { } int64_t TextServerFallback::font_get_face_count(const RID &p_font_rid) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0); MutexLock lock(fd->mutex); @@ -964,8 +962,8 @@ int64_t TextServerFallback::font_get_face_count(const RID &p_font_rid) const { return face_count; } -int64_t /*FontStyle*/ TextServerFallback::font_get_style(const RID &p_font_rid) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); +BitField<TextServer::FontStyle> TextServerFallback::font_get_style(const RID &p_font_rid) const { + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0); MutexLock lock(fd->mutex); @@ -975,7 +973,7 @@ int64_t /*FontStyle*/ TextServerFallback::font_get_style(const RID &p_font_rid) } void TextServerFallback::font_set_style_name(const RID &p_font_rid, const String &p_name) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -985,7 +983,7 @@ void TextServerFallback::font_set_style_name(const RID &p_font_rid, const String } String TextServerFallback::font_get_style_name(const RID &p_font_rid) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, String()); MutexLock lock(fd->mutex); @@ -995,7 +993,7 @@ String TextServerFallback::font_get_style_name(const RID &p_font_rid) const { } void TextServerFallback::font_set_name(const RID &p_font_rid, const String &p_name) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1005,7 +1003,7 @@ void TextServerFallback::font_set_name(const RID &p_font_rid, const String &p_na } String TextServerFallback::font_get_name(const RID &p_font_rid) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, String()); MutexLock lock(fd->mutex); @@ -1015,7 +1013,7 @@ String TextServerFallback::font_get_name(const RID &p_font_rid) const { } void TextServerFallback::font_set_antialiased(const RID &p_font_rid, bool p_antialiased) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1026,7 +1024,7 @@ void TextServerFallback::font_set_antialiased(const RID &p_font_rid, bool p_anti } bool TextServerFallback::font_is_antialiased(const RID &p_font_rid) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -1034,12 +1032,12 @@ bool TextServerFallback::font_is_antialiased(const RID &p_font_rid) const { } void TextServerFallback::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); if (fd->mipmaps != p_generate_mipmaps) { - for (KeyValue<Vector2i, FontDataForSizeFallback *> &E : fd->cache) { + for (KeyValue<Vector2i, FontForSizeFallback *> &E : fd->cache) { for (int i = 0; i < E.value->textures.size(); i++) { E.value->textures.write[i].dirty = true; } @@ -1049,7 +1047,7 @@ void TextServerFallback::font_set_generate_mipmaps(const RID &p_font_rid, bool p } bool TextServerFallback::font_get_generate_mipmaps(const RID &p_font_rid) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -1057,7 +1055,7 @@ bool TextServerFallback::font_get_generate_mipmaps(const RID &p_font_rid) const } void TextServerFallback::font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1068,7 +1066,7 @@ void TextServerFallback::font_set_multichannel_signed_distance_field(const RID & } bool TextServerFallback::font_is_multichannel_signed_distance_field(const RID &p_font_rid) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -1076,7 +1074,7 @@ bool TextServerFallback::font_is_multichannel_signed_distance_field(const RID &p } void TextServerFallback::font_set_msdf_pixel_range(const RID &p_font_rid, int64_t p_msdf_pixel_range) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1087,7 +1085,7 @@ void TextServerFallback::font_set_msdf_pixel_range(const RID &p_font_rid, int64_ } int64_t TextServerFallback::font_get_msdf_pixel_range(const RID &p_font_rid) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -1095,7 +1093,7 @@ int64_t TextServerFallback::font_get_msdf_pixel_range(const RID &p_font_rid) con } void TextServerFallback::font_set_msdf_size(const RID &p_font_rid, int64_t p_msdf_size) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1106,7 +1104,7 @@ void TextServerFallback::font_set_msdf_size(const RID &p_font_rid, int64_t p_msd } int64_t TextServerFallback::font_get_msdf_size(const RID &p_font_rid) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -1114,7 +1112,7 @@ int64_t TextServerFallback::font_get_msdf_size(const RID &p_font_rid) const { } void TextServerFallback::font_set_fixed_size(const RID &p_font_rid, int64_t p_fixed_size) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1122,7 +1120,7 @@ void TextServerFallback::font_set_fixed_size(const RID &p_font_rid, int64_t p_fi } int64_t TextServerFallback::font_get_fixed_size(const RID &p_font_rid) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -1130,7 +1128,7 @@ int64_t TextServerFallback::font_get_fixed_size(const RID &p_font_rid) const { } void TextServerFallback::font_set_force_autohinter(const RID &p_font_rid, bool p_force_autohinter) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1141,7 +1139,7 @@ void TextServerFallback::font_set_force_autohinter(const RID &p_font_rid, bool p } bool TextServerFallback::font_is_force_autohinter(const RID &p_font_rid) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -1149,7 +1147,7 @@ bool TextServerFallback::font_is_force_autohinter(const RID &p_font_rid) const { } void TextServerFallback::font_set_hinting(const RID &p_font_rid, TextServer::Hinting p_hinting) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1160,7 +1158,7 @@ void TextServerFallback::font_set_hinting(const RID &p_font_rid, TextServer::Hin } TextServer::Hinting TextServerFallback::font_get_hinting(const RID &p_font_rid) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, HINTING_NONE); MutexLock lock(fd->mutex); @@ -1168,7 +1166,7 @@ TextServer::Hinting TextServerFallback::font_get_hinting(const RID &p_font_rid) } void TextServerFallback::font_set_subpixel_positioning(const RID &p_font_rid, TextServer::SubpixelPositioning p_subpixel) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1176,7 +1174,7 @@ void TextServerFallback::font_set_subpixel_positioning(const RID &p_font_rid, Te } TextServer::SubpixelPositioning TextServerFallback::font_get_subpixel_positioning(const RID &p_font_rid) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, SUBPIXEL_POSITIONING_DISABLED); MutexLock lock(fd->mutex); @@ -1184,7 +1182,7 @@ TextServer::SubpixelPositioning TextServerFallback::font_get_subpixel_positionin } void TextServerFallback::font_set_embolden(const RID &p_font_rid, double p_strength) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1195,7 +1193,7 @@ void TextServerFallback::font_set_embolden(const RID &p_font_rid, double p_stren } double TextServerFallback::font_get_embolden(const RID &p_font_rid) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0.0); MutexLock lock(fd->mutex); @@ -1203,7 +1201,7 @@ double TextServerFallback::font_get_embolden(const RID &p_font_rid) const { } void TextServerFallback::font_set_transform(const RID &p_font_rid, const Transform2D &p_transform) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1214,7 +1212,7 @@ void TextServerFallback::font_set_transform(const RID &p_font_rid, const Transfo } Transform2D TextServerFallback::font_get_transform(const RID &p_font_rid) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Transform2D()); MutexLock lock(fd->mutex); @@ -1222,7 +1220,7 @@ Transform2D TextServerFallback::font_get_transform(const RID &p_font_rid) const } void TextServerFallback::font_set_variation_coordinates(const RID &p_font_rid, const Dictionary &p_variation_coordinates) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1233,7 +1231,7 @@ void TextServerFallback::font_set_variation_coordinates(const RID &p_font_rid, c } Dictionary TextServerFallback::font_get_variation_coordinates(const RID &p_font_rid) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Dictionary()); MutexLock lock(fd->mutex); @@ -1241,7 +1239,7 @@ Dictionary TextServerFallback::font_get_variation_coordinates(const RID &p_font_ } void TextServerFallback::font_set_oversampling(const RID &p_font_rid, double p_oversampling) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1252,7 +1250,7 @@ void TextServerFallback::font_set_oversampling(const RID &p_font_rid, double p_o } double TextServerFallback::font_get_oversampling(const RID &p_font_rid) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0.0); MutexLock lock(fd->mutex); @@ -1260,30 +1258,30 @@ double TextServerFallback::font_get_oversampling(const RID &p_font_rid) const { } Array TextServerFallback::font_get_size_cache_list(const RID &p_font_rid) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Array()); MutexLock lock(fd->mutex); Array ret; - for (const KeyValue<Vector2i, FontDataForSizeFallback *> &E : fd->cache) { + for (const KeyValue<Vector2i, FontForSizeFallback *> &E : fd->cache) { ret.push_back(E.key); } return ret; } void TextServerFallback::font_clear_size_cache(const RID &p_font_rid) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); - for (const KeyValue<Vector2i, FontDataForSizeFallback *> &E : fd->cache) { + for (const KeyValue<Vector2i, FontForSizeFallback *> &E : fd->cache) { memdelete(E.value); } fd->cache.clear(); } void TextServerFallback::font_remove_size_cache(const RID &p_font_rid, const Vector2i &p_size) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1294,7 +1292,7 @@ void TextServerFallback::font_remove_size_cache(const RID &p_font_rid, const Vec } void TextServerFallback::font_set_ascent(const RID &p_font_rid, int64_t p_size, double p_ascent) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1305,7 +1303,7 @@ void TextServerFallback::font_set_ascent(const RID &p_font_rid, int64_t p_size, } double TextServerFallback::font_get_ascent(const RID &p_font_rid, int64_t p_size) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0.0); MutexLock lock(fd->mutex); @@ -1321,7 +1319,7 @@ double TextServerFallback::font_get_ascent(const RID &p_font_rid, int64_t p_size } void TextServerFallback::font_set_descent(const RID &p_font_rid, int64_t p_size, double p_descent) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); Vector2i size = _get_size(fd, p_size); @@ -1331,7 +1329,7 @@ void TextServerFallback::font_set_descent(const RID &p_font_rid, int64_t p_size, } double TextServerFallback::font_get_descent(const RID &p_font_rid, int64_t p_size) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0.0); MutexLock lock(fd->mutex); @@ -1347,7 +1345,7 @@ double TextServerFallback::font_get_descent(const RID &p_font_rid, int64_t p_siz } void TextServerFallback::font_set_underline_position(const RID &p_font_rid, int64_t p_size, double p_underline_position) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1358,7 +1356,7 @@ void TextServerFallback::font_set_underline_position(const RID &p_font_rid, int6 } double TextServerFallback::font_get_underline_position(const RID &p_font_rid, int64_t p_size) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0.0); MutexLock lock(fd->mutex); @@ -1374,7 +1372,7 @@ double TextServerFallback::font_get_underline_position(const RID &p_font_rid, in } void TextServerFallback::font_set_underline_thickness(const RID &p_font_rid, int64_t p_size, double p_underline_thickness) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1385,7 +1383,7 @@ void TextServerFallback::font_set_underline_thickness(const RID &p_font_rid, int } double TextServerFallback::font_get_underline_thickness(const RID &p_font_rid, int64_t p_size) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0.0); MutexLock lock(fd->mutex); @@ -1401,7 +1399,7 @@ double TextServerFallback::font_get_underline_thickness(const RID &p_font_rid, i } void TextServerFallback::font_set_scale(const RID &p_font_rid, int64_t p_size, double p_scale) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1417,7 +1415,7 @@ void TextServerFallback::font_set_scale(const RID &p_font_rid, int64_t p_size, d } double TextServerFallback::font_get_scale(const RID &p_font_rid, int64_t p_size) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0.0); MutexLock lock(fd->mutex); @@ -1432,60 +1430,8 @@ double TextServerFallback::font_get_scale(const RID &p_font_rid, int64_t p_size) } } -void TextServerFallback::font_set_spacing(const RID &p_font_rid, int64_t p_size, TextServer::SpacingType p_spacing, int64_t p_value) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); - ERR_FAIL_COND(!fd); - - MutexLock lock(fd->mutex); - Vector2i size = _get_size(fd, p_size); - - ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); - switch (p_spacing) { - case TextServer::SPACING_GLYPH: { - fd->cache[size]->spacing_glyph = p_value; - } break; - case TextServer::SPACING_SPACE: { - fd->cache[size]->spacing_space = p_value; - } break; - default: { - ERR_FAIL_MSG("Invalid spacing type: " + String::num_int64(p_spacing)); - } break; - } -} - -int64_t TextServerFallback::font_get_spacing(const RID &p_font_rid, int64_t p_size, TextServer::SpacingType p_spacing) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); - ERR_FAIL_COND_V(!fd, 0); - - MutexLock lock(fd->mutex); - Vector2i size = _get_size(fd, p_size); - - ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), 0); - - switch (p_spacing) { - case TextServer::SPACING_GLYPH: { - if (fd->msdf) { - return fd->cache[size]->spacing_glyph * (double)p_size / (double)fd->msdf_source_size; - } else { - return fd->cache[size]->spacing_glyph; - } - } break; - case TextServer::SPACING_SPACE: { - if (fd->msdf) { - return fd->cache[size]->spacing_space * (double)p_size / (double)fd->msdf_source_size; - } else { - return fd->cache[size]->spacing_space; - } - } break; - default: { - ERR_FAIL_V_MSG(0, "Invalid spacing type: " + String::num_int64(p_spacing)); - } break; - } - return 0; -} - int64_t TextServerFallback::font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, 0); MutexLock lock(fd->mutex); @@ -1497,7 +1443,7 @@ int64_t TextServerFallback::font_get_texture_count(const RID &p_font_rid, const } void TextServerFallback::font_clear_textures(const RID &p_font_rid, const Vector2i &p_size) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); Vector2i size = _get_size_outline(fd, p_size); @@ -1507,7 +1453,7 @@ void TextServerFallback::font_clear_textures(const RID &p_font_rid, const Vector } void TextServerFallback::font_remove_texture(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1519,7 +1465,7 @@ void TextServerFallback::font_remove_texture(const RID &p_font_rid, const Vector } void TextServerFallback::font_set_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const Ref<Image> &p_image) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); ERR_FAIL_COND(p_image.is_null()); @@ -1545,14 +1491,12 @@ void TextServerFallback::font_set_texture_image(const RID &p_font_rid, const Vec img->generate_mipmaps(); } - tex.texture = Ref<ImageTexture>(); - tex.texture.instantiate(); - tex.texture->create_from_image(img); + tex.texture = ImageTexture::create_from_image(img); tex.dirty = false; } Ref<Image> TextServerFallback::font_get_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Ref<Image>()); MutexLock lock(fd->mutex); @@ -1569,7 +1513,7 @@ Ref<Image> TextServerFallback::font_get_texture_image(const RID &p_font_rid, con } void TextServerFallback::font_set_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const PackedInt32Array &p_offset) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1585,7 +1529,7 @@ void TextServerFallback::font_set_texture_offsets(const RID &p_font_rid, const V } PackedInt32Array TextServerFallback::font_get_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, PackedInt32Array()); MutexLock lock(fd->mutex); @@ -1598,7 +1542,7 @@ PackedInt32Array TextServerFallback::font_get_texture_offsets(const RID &p_font_ } Array TextServerFallback::font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Array()); MutexLock lock(fd->mutex); @@ -1614,7 +1558,7 @@ Array TextServerFallback::font_get_glyph_list(const RID &p_font_rid, const Vecto } void TextServerFallback::font_clear_glyphs(const RID &p_font_rid, const Vector2i &p_size) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1625,7 +1569,7 @@ void TextServerFallback::font_clear_glyphs(const RID &p_font_rid, const Vector2i } void TextServerFallback::font_remove_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1636,7 +1580,7 @@ void TextServerFallback::font_remove_glyph(const RID &p_font_rid, const Vector2i } Vector2 TextServerFallback::font_get_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Vector2()); MutexLock lock(fd->mutex); @@ -1664,7 +1608,7 @@ Vector2 TextServerFallback::font_get_glyph_advance(const RID &p_font_rid, int64_ } void TextServerFallback::font_set_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph, const Vector2 &p_advance) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1679,7 +1623,7 @@ void TextServerFallback::font_set_glyph_advance(const RID &p_font_rid, int64_t p } Vector2 TextServerFallback::font_get_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Vector2()); MutexLock lock(fd->mutex); @@ -1700,7 +1644,7 @@ Vector2 TextServerFallback::font_get_glyph_offset(const RID &p_font_rid, const V } void TextServerFallback::font_set_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_offset) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1715,7 +1659,7 @@ void TextServerFallback::font_set_glyph_offset(const RID &p_font_rid, const Vect } Vector2 TextServerFallback::font_get_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Vector2()); MutexLock lock(fd->mutex); @@ -1736,7 +1680,7 @@ Vector2 TextServerFallback::font_get_glyph_size(const RID &p_font_rid, const Vec } void TextServerFallback::font_set_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_gl_size) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1751,7 +1695,7 @@ void TextServerFallback::font_set_glyph_size(const RID &p_font_rid, const Vector } Rect2 TextServerFallback::font_get_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Rect2()); MutexLock lock(fd->mutex); @@ -1767,7 +1711,7 @@ Rect2 TextServerFallback::font_get_glyph_uv_rect(const RID &p_font_rid, const Ve } void TextServerFallback::font_set_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Rect2 &p_uv_rect) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1782,7 +1726,7 @@ void TextServerFallback::font_set_glyph_uv_rect(const RID &p_font_rid, const Vec } int64_t TextServerFallback::font_get_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, -1); MutexLock lock(fd->mutex); @@ -1798,7 +1742,7 @@ int64_t TextServerFallback::font_get_glyph_texture_idx(const RID &p_font_rid, co } void TextServerFallback::font_set_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, int64_t p_texture_idx) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1813,7 +1757,7 @@ void TextServerFallback::font_set_glyph_texture_idx(const RID &p_font_rid, const } RID TextServerFallback::font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, RID()); MutexLock lock(fd->mutex); @@ -1838,8 +1782,7 @@ RID TextServerFallback::font_get_glyph_texture_rid(const RID &p_font_rid, const img->generate_mipmaps(); } if (tex.texture.is_null()) { - tex.texture.instantiate(); - tex.texture->create_from_image(img); + tex.texture = ImageTexture::create_from_image(img); } else { tex.texture->update(img); } @@ -1853,7 +1796,7 @@ RID TextServerFallback::font_get_glyph_texture_rid(const RID &p_font_rid, const } Size2 TextServerFallback::font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Size2()); MutexLock lock(fd->mutex); @@ -1878,8 +1821,7 @@ Size2 TextServerFallback::font_get_glyph_texture_size(const RID &p_font_rid, con img->generate_mipmaps(); } if (tex.texture.is_null()) { - tex.texture.instantiate(); - tex.texture->create_from_image(img); + tex.texture = ImageTexture::create_from_image(img); } else { tex.texture->update(img); } @@ -1893,7 +1835,7 @@ Size2 TextServerFallback::font_get_glyph_texture_size(const RID &p_font_rid, con } Dictionary TextServerFallback::font_get_glyph_contours(const RID &p_font_rid, int64_t p_size, int64_t p_index) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Dictionary()); MutexLock lock(fd->mutex); @@ -1943,7 +1885,7 @@ Dictionary TextServerFallback::font_get_glyph_contours(const RID &p_font_rid, in } Array TextServerFallback::font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Array()); MutexLock lock(fd->mutex); @@ -1959,7 +1901,7 @@ Array TextServerFallback::font_get_kerning_list(const RID &p_font_rid, int64_t p } void TextServerFallback::font_clear_kerning_map(const RID &p_font_rid, int64_t p_size) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1970,7 +1912,7 @@ void TextServerFallback::font_clear_kerning_map(const RID &p_font_rid, int64_t p } void TextServerFallback::font_remove_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1981,7 +1923,7 @@ void TextServerFallback::font_remove_kerning(const RID &p_font_rid, int64_t p_si } void TextServerFallback::font_set_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -1992,7 +1934,7 @@ void TextServerFallback::font_set_kerning(const RID &p_font_rid, int64_t p_size, } Vector2 TextServerFallback::font_get_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Vector2()); MutexLock lock(fd->mutex); @@ -2032,7 +1974,7 @@ int64_t TextServerFallback::font_get_glyph_index(const RID &p_font_rid, int64_t } bool TextServerFallback::font_has_char(const RID &p_font_rid, int64_t p_char) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); ERR_FAIL_COND_V_MSG((p_char >= 0xd800 && p_char <= 0xdfff) || (p_char > 0x10ffff), false, "Unicode parsing error: Invalid unicode codepoint " + String::num_int64(p_char, 16) + "."); @@ -2040,7 +1982,7 @@ bool TextServerFallback::font_has_char(const RID &p_font_rid, int64_t p_char) co if (fd->cache.is_empty()) { ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, fd->msdf ? Vector2i(fd->msdf_source_size, 0) : Vector2i(16, 0)), false); } - FontDataForSizeFallback *at_size = fd->cache.begin()->value; + FontForSizeFallback *at_size = fd->cache.begin()->value; #ifdef MODULE_FREETYPE_ENABLED if (at_size && at_size->face) { @@ -2051,14 +1993,14 @@ bool TextServerFallback::font_has_char(const RID &p_font_rid, int64_t p_char) co } String TextServerFallback::font_get_supported_chars(const RID &p_font_rid) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, String()); MutexLock lock(fd->mutex); if (fd->cache.is_empty()) { ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, fd->msdf ? Vector2i(fd->msdf_source_size, 0) : Vector2i(16, 0)), String()); } - FontDataForSizeFallback *at_size = fd->cache.begin()->value; + FontForSizeFallback *at_size = fd->cache.begin()->value; String chars; #ifdef MODULE_FREETYPE_ENABLED @@ -2084,7 +2026,7 @@ String TextServerFallback::font_get_supported_chars(const RID &p_font_rid) const } void TextServerFallback::font_render_range(const RID &p_font_rid, const Vector2i &p_size, int64_t p_start, int64_t p_end) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); ERR_FAIL_COND_MSG((p_start >= 0xd800 && p_start <= 0xdfff) || (p_start > 0x10ffff), "Unicode parsing error: Invalid unicode codepoint " + String::num_int64(p_start, 16) + "."); ERR_FAIL_COND_MSG((p_end >= 0xd800 && p_end <= 0xdfff) || (p_end > 0x10ffff), "Unicode parsing error: Invalid unicode codepoint " + String::num_int64(p_end, 16) + "."); @@ -2117,7 +2059,7 @@ void TextServerFallback::font_render_range(const RID &p_font_rid, const Vector2i } void TextServerFallback::font_render_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_index) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2146,7 +2088,7 @@ void TextServerFallback::font_render_glyph(const RID &p_font_rid, const Vector2i } void TextServerFallback::font_draw_glyph(const RID &p_font_rid, const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2192,8 +2134,7 @@ void TextServerFallback::font_draw_glyph(const RID &p_font_rid, const RID &p_can img->generate_mipmaps(); } if (tex.texture.is_null()) { - tex.texture.instantiate(); - tex.texture->create_from_image(img); + tex.texture = ImageTexture::create_from_image(img); } else { tex.texture->update(img); } @@ -2225,7 +2166,7 @@ void TextServerFallback::font_draw_glyph(const RID &p_font_rid, const RID &p_can } void TextServerFallback::font_draw_glyph_outline(const RID &p_font_rid, const RID &p_canvas, int64_t p_size, int64_t p_outline_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2271,8 +2212,7 @@ void TextServerFallback::font_draw_glyph_outline(const RID &p_font_rid, const RI img->generate_mipmaps(); } if (tex.texture.is_null()) { - tex.texture.instantiate(); - tex.texture->create_from_image(img); + tex.texture = ImageTexture::create_from_image(img); } else { tex.texture->update(img); } @@ -2304,7 +2244,7 @@ void TextServerFallback::font_draw_glyph_outline(const RID &p_font_rid, const RI } bool TextServerFallback::font_is_language_supported(const RID &p_font_rid, const String &p_language) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -2316,7 +2256,7 @@ bool TextServerFallback::font_is_language_supported(const RID &p_font_rid, const } void TextServerFallback::font_set_language_support_override(const RID &p_font_rid, const String &p_language, bool p_supported) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2324,7 +2264,7 @@ void TextServerFallback::font_set_language_support_override(const RID &p_font_ri } bool TextServerFallback::font_get_language_support_override(const RID &p_font_rid, const String &p_language) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -2332,7 +2272,7 @@ bool TextServerFallback::font_get_language_support_override(const RID &p_font_ri } void TextServerFallback::font_remove_language_support_override(const RID &p_font_rid, const String &p_language) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2340,7 +2280,7 @@ void TextServerFallback::font_remove_language_support_override(const RID &p_font } PackedStringArray TextServerFallback::font_get_language_support_overrides(const RID &p_font_rid) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, PackedStringArray()); MutexLock lock(fd->mutex); @@ -2352,7 +2292,7 @@ PackedStringArray TextServerFallback::font_get_language_support_overrides(const } bool TextServerFallback::font_is_script_supported(const RID &p_font_rid, const String &p_script) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -2364,7 +2304,7 @@ bool TextServerFallback::font_is_script_supported(const RID &p_font_rid, const S } void TextServerFallback::font_set_script_support_override(const RID &p_font_rid, const String &p_script, bool p_supported) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2372,7 +2312,7 @@ void TextServerFallback::font_set_script_support_override(const RID &p_font_rid, } bool TextServerFallback::font_get_script_support_override(const RID &p_font_rid, const String &p_script) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, false); MutexLock lock(fd->mutex); @@ -2380,7 +2320,7 @@ bool TextServerFallback::font_get_script_support_override(const RID &p_font_rid, } void TextServerFallback::font_remove_script_support_override(const RID &p_font_rid, const String &p_script) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2390,7 +2330,7 @@ void TextServerFallback::font_remove_script_support_override(const RID &p_font_r } PackedStringArray TextServerFallback::font_get_script_support_overrides(const RID &p_font_rid) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, PackedStringArray()); MutexLock lock(fd->mutex); @@ -2402,7 +2342,7 @@ PackedStringArray TextServerFallback::font_get_script_support_overrides(const RI } void TextServerFallback::font_set_opentype_feature_overrides(const RID &p_font_rid, const Dictionary &p_overrides) { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); @@ -2412,7 +2352,7 @@ void TextServerFallback::font_set_opentype_feature_overrides(const RID &p_font_r } Dictionary TextServerFallback::font_get_opentype_feature_overrides(const RID &p_font_rid) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Dictionary()); MutexLock lock(fd->mutex); @@ -2424,7 +2364,7 @@ Dictionary TextServerFallback::font_supported_feature_list(const RID &p_font_rid } Dictionary TextServerFallback::font_supported_variation_list(const RID &p_font_rid) const { - FontDataFallback *fd = font_owner.get_or_null(p_font_rid); + FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND_V(!fd, Dictionary()); MutexLock lock(fd->mutex); @@ -2630,6 +2570,31 @@ bool TextServerFallback::shaped_text_get_preserve_control(const RID &p_shaped) c return sd->preserve_control; } +void TextServerFallback::shaped_text_set_spacing(const RID &p_shaped, SpacingType p_spacing, int64_t p_value) { + ERR_FAIL_INDEX((int)p_spacing, 4); + ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND(!sd); + + MutexLock lock(sd->mutex); + if (sd->extra_spacing[p_spacing] != p_value) { + if (sd->parent != RID()) { + full_copy(sd); + } + sd->extra_spacing[p_spacing] = p_value; + invalidate(sd); + } +} + +int64_t TextServerFallback::shaped_text_get_spacing(const RID &p_shaped, SpacingType p_spacing) const { + ERR_FAIL_INDEX_V((int)p_spacing, 4, 0); + + const ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped); + ERR_FAIL_COND_V(!sd, 0); + + MutexLock lock(sd->mutex); + return sd->extra_spacing[p_spacing]; +} + int64_t TextServerFallback::shaped_get_span_count(const RID &p_shaped) const { ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, 0); @@ -2912,6 +2877,9 @@ RID TextServerFallback::shaped_text_substr(const RID &p_shaped, int64_t p_start, new_sd->sort_valid = false; new_sd->upos = sd->upos; new_sd->uthk = sd->uthk; + for (int i = 0; i < TextServer::SPACING_MAX; i++) { + new_sd->extra_spacing[i] = sd->extra_spacing[i]; + } if (p_length > 0) { new_sd->text = sd->text.substr(p_start - sd->start, p_length); @@ -2980,7 +2948,7 @@ RID TextServerFallback::shaped_text_get_parent(const RID &p_shaped) const { return sd->parent; } -double TextServerFallback::shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t /*JustificationFlag*/ p_jst_flags) { +double TextServerFallback::shaped_text_fit_to_width(const RID &p_shaped, double p_width, BitField<JustificationFlag> p_jst_flags) { ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped); ERR_FAIL_COND_V(!sd, 0.0); @@ -2995,7 +2963,7 @@ double TextServerFallback::shaped_text_fit_to_width(const RID &p_shaped, double int start_pos = 0; int end_pos = sd->glyphs.size() - 1; - if ((p_jst_flags & JUSTIFICATION_AFTER_LAST_TAB) == JUSTIFICATION_AFTER_LAST_TAB) { + if (p_jst_flags.has_flag(JUSTIFICATION_AFTER_LAST_TAB)) { int start, end, delta; if (sd->para_direction == DIRECTION_LTR) { start = sd->glyphs.size() - 1; @@ -3021,7 +2989,7 @@ double TextServerFallback::shaped_text_fit_to_width(const RID &p_shaped, double } double justification_width; - if ((p_jst_flags & JUSTIFICATION_CONSTRAIN_ELLIPSIS) == JUSTIFICATION_CONSTRAIN_ELLIPSIS) { + if (p_jst_flags.has_flag(JUSTIFICATION_CONSTRAIN_ELLIPSIS)) { if (sd->overrun_trim_data.trim_pos >= 0) { end_pos = sd->overrun_trim_data.trim_pos; justification_width = sd->width_trimmed; @@ -3032,7 +3000,7 @@ double TextServerFallback::shaped_text_fit_to_width(const RID &p_shaped, double justification_width = sd->width; } - if ((p_jst_flags & JUSTIFICATION_TRIM_EDGE_SPACES) == JUSTIFICATION_TRIM_EDGE_SPACES) { + if (p_jst_flags.has_flag(JUSTIFICATION_TRIM_EDGE_SPACES)) { // Trim spaces. while ((start_pos < end_pos) && ((sd->glyphs[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (sd->glyphs[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (sd->glyphs[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) { justification_width -= sd->glyphs[start_pos].advance * sd->glyphs[start_pos].repeat; @@ -3064,7 +3032,7 @@ double TextServerFallback::shaped_text_fit_to_width(const RID &p_shaped, double } } - if ((space_count > 0) && ((p_jst_flags & JUSTIFICATION_WORD_BOUND) == JUSTIFICATION_WORD_BOUND)) { + if ((space_count > 0) && p_jst_flags.has_flag(JUSTIFICATION_WORD_BOUND)) { double delta_width_per_space = (p_width - justification_width) / space_count; for (int i = start_pos; i <= end_pos; i++) { Glyph &gl = sd->glyphs.write[i]; @@ -3082,7 +3050,7 @@ double TextServerFallback::shaped_text_fit_to_width(const RID &p_shaped, double sd->fit_width_minimum_reached = true; } - if ((p_jst_flags & JUSTIFICATION_CONSTRAIN_ELLIPSIS) != JUSTIFICATION_CONSTRAIN_ELLIPSIS) { + if (!p_jst_flags.has_flag(JUSTIFICATION_CONSTRAIN_ELLIPSIS)) { sd->width = justification_width; } @@ -3217,7 +3185,7 @@ bool TextServerFallback::shaped_text_update_justification_ops(const RID &p_shape return true; } -void TextServerFallback::shaped_text_overrun_trim_to_width(const RID &p_shaped_line, double p_width, int64_t p_trim_flags) { +void TextServerFallback::shaped_text_overrun_trim_to_width(const RID &p_shaped_line, double p_width, BitField<TextServer::TextOverrunFlag> p_trim_flags) { ShapedTextDataFallback *sd = shaped_owner.get_or_null(p_shaped_line); ERR_FAIL_COND_MSG(!sd, "ShapedTextDataFallback invalid."); @@ -3229,14 +3197,14 @@ void TextServerFallback::shaped_text_overrun_trim_to_width(const RID &p_shaped_l sd->text_trimmed = false; sd->overrun_trim_data.ellipsis_glyph_buf.clear(); - bool add_ellipsis = (p_trim_flags & OVERRUN_ADD_ELLIPSIS) == OVERRUN_ADD_ELLIPSIS; - bool cut_per_word = (p_trim_flags & OVERRUN_TRIM_WORD_ONLY) == OVERRUN_TRIM_WORD_ONLY; - bool enforce_ellipsis = (p_trim_flags & OVERRUN_ENFORCE_ELLIPSIS) == OVERRUN_ENFORCE_ELLIPSIS; - bool justification_aware = (p_trim_flags & OVERRUN_JUSTIFICATION_AWARE) == OVERRUN_JUSTIFICATION_AWARE; + bool add_ellipsis = p_trim_flags.has_flag(OVERRUN_ADD_ELLIPSIS); + bool cut_per_word = p_trim_flags.has_flag(OVERRUN_TRIM_WORD_ONLY); + bool enforce_ellipsis = p_trim_flags.has_flag(OVERRUN_ENFORCE_ELLIPSIS); + bool justification_aware = p_trim_flags.has_flag(OVERRUN_JUSTIFICATION_AWARE); Glyph *sd_glyphs = sd->glyphs.ptrw(); - if ((p_trim_flags & OVERRUN_TRIM) == OVERRUN_NO_TRIM || sd_glyphs == nullptr || p_width <= 0 || !(sd->width > p_width || enforce_ellipsis)) { + if (p_trim_flags.has_flag(OVERRUN_TRIM) || sd_glyphs == nullptr || p_width <= 0 || !(sd->width > p_width || enforce_ellipsis)) { sd->overrun_trim_data.trim_pos = -1; sd->overrun_trim_data.ellipsis_pos = -1; return; @@ -3289,7 +3257,7 @@ void TextServerFallback::shaped_text_overrun_trim_to_width(const RID &p_shaped_l int ellipsis_width = 0; if (add_ellipsis && whitespace_gl_font_rid.is_valid()) { - ellipsis_width = 3 * dot_adv.x + font_get_spacing(whitespace_gl_font_rid, last_gl_font_size, SPACING_GLYPH) + (cut_per_word ? whitespace_adv.x : 0); + ellipsis_width = 3 * dot_adv.x + sd->extra_spacing[SPACING_GLYPH] + (cut_per_word ? whitespace_adv.x : 0); } int ell_min_characters = 6; @@ -3491,10 +3459,13 @@ bool TextServerFallback::shaped_text_shape(const RID &p_shaped) { sd->descent = MAX(sd->descent, Math::round(font_get_glyph_advance(gl.font_rid, gl.font_size, gl.index).x * 0.5)); } } - if (font_get_spacing(gl.font_rid, gl.font_size, TextServer::SPACING_SPACE) && is_whitespace(sd->text[j - sd->start])) { - gl.advance += font_get_spacing(gl.font_rid, gl.font_size, TextServer::SPACING_SPACE); - } else { - gl.advance += font_get_spacing(gl.font_rid, gl.font_size, TextServer::SPACING_GLYPH); + if (j < sd->end - 1) { + // Do not add extra spacing to the last glyph of the string. + if (is_whitespace(sd->text[j - sd->start])) { + gl.advance += sd->extra_spacing[SPACING_SPACE]; + } else { + gl.advance += sd->extra_spacing[SPACING_GLYPH]; + } } sd->upos = MAX(sd->upos, font_get_underline_position(gl.font_rid, gl.font_size)); sd->uthk = MAX(sd->uthk, font_get_underline_thickness(gl.font_rid, gl.font_size)); @@ -3621,9 +3592,9 @@ Size2 TextServerFallback::shaped_text_get_size(const RID &p_shaped) const { const_cast<TextServerFallback *>(this)->shaped_text_shape(p_shaped); } if (sd->orientation == TextServer::ORIENTATION_HORIZONTAL) { - return Size2(sd->width, sd->ascent + sd->descent).ceil(); + return Size2(sd->width, sd->ascent + sd->descent + sd->extra_spacing[SPACING_TOP] + sd->extra_spacing[SPACING_BOTTOM]).ceil(); } else { - return Size2(sd->ascent + sd->descent, sd->width).ceil(); + return Size2(sd->ascent + sd->descent + sd->extra_spacing[SPACING_TOP] + sd->extra_spacing[SPACING_BOTTOM], sd->width).ceil(); } } @@ -3635,7 +3606,7 @@ double TextServerFallback::shaped_text_get_ascent(const RID &p_shaped) const { if (!sd->valid) { const_cast<TextServerFallback *>(this)->shaped_text_shape(p_shaped); } - return sd->ascent; + return sd->ascent + sd->extra_spacing[SPACING_TOP]; } double TextServerFallback::shaped_text_get_descent(const RID &p_shaped) const { @@ -3646,7 +3617,7 @@ double TextServerFallback::shaped_text_get_descent(const RID &p_shaped) const { if (!sd->valid) { const_cast<TextServerFallback *>(this)->shaped_text_shape(p_shaped); } - return sd->descent; + return sd->descent + sd->extra_spacing[SPACING_BOTTOM]; } double TextServerFallback::shaped_text_get_width(const RID &p_shaped) const { diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h index e4c81aed5b..adb5cbb817 100644 --- a/modules/text_server_fb/text_server_fb.h +++ b/modules/text_server_fb/text_server_fb.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef TEXT_SERVER_FALLBACK_H -#define TEXT_SERVER_FALLBACK_H +#ifndef TEXT_SERVER_FB_H +#define TEXT_SERVER_FB_H /*************************************************************************/ /* Fallback Text Server provides simplified TS functionality, without */ @@ -79,9 +79,9 @@ using namespace godot; #include "servers/text/text_server_extension.h" +#include "core/object/worker_thread_pool.h" #include "core/templates/hash_map.h" #include "core/templates/rid_owner.h" -#include "core/templates/thread_work_pool.h" #include "scene/resources/texture.h" #include "modules/modules_enabled.gen.h" // For freetype, msdfgen. @@ -144,7 +144,7 @@ class TextServerFallback : public TextServerExtension { Vector2 advance; }; - struct FontDataForSizeFallback { + struct FontForSizeFallback { double ascent = 0.0; double descent = 0.0; double underline_position = 0.0; @@ -152,9 +152,6 @@ class TextServerFallback : public TextServerExtension { double scale = 1.0; double oversampling = 1.0; - int spacing_glyph = 0; - int spacing_space = 0; - Vector2i size; Vector<FontTexture> textures; @@ -166,7 +163,7 @@ class TextServerFallback : public TextServerExtension { FT_StreamRec stream; #endif - ~FontDataForSizeFallback() { + ~FontForSizeFallback() { #ifdef MODULE_FREETYPE_ENABLED if (face != nullptr) { FT_Done_Face(face); @@ -175,7 +172,7 @@ class TextServerFallback : public TextServerExtension { } }; - struct FontDataFallback { + struct FontFallback { Mutex mutex; bool antialiased = true; @@ -192,11 +189,11 @@ class TextServerFallback : public TextServerExtension { double embolden = 0.0; Transform2D transform; - uint32_t style_flags = 0; + BitField<TextServer::FontStyle> style_flags = 0; String font_name; String style_name; - HashMap<Vector2i, FontDataForSizeFallback *, VariantHasher, VariantComparator> cache; + HashMap<Vector2i, FontForSizeFallback *, VariantHasher, VariantComparator> cache; bool face_init = false; Dictionary supported_varaitions; @@ -211,30 +208,27 @@ class TextServerFallback : public TextServerExtension { size_t data_size; int face_index = 0; - mutable ThreadWorkPool work_pool; - - ~FontDataFallback() { - work_pool.finish(); - for (const KeyValue<Vector2i, FontDataForSizeFallback *> &E : cache) { + ~FontFallback() { + for (const KeyValue<Vector2i, FontForSizeFallback *> &E : cache) { memdelete(E.value); } cache.clear(); } }; - _FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontDataForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const; + _FORCE_INLINE_ FontTexturePosition find_texture_pos_for_glyph(FontForSizeFallback *p_data, int p_color_size, Image::Format p_image_format, int p_width, int p_height, bool p_msdf) const; #ifdef MODULE_MSDFGEN_ENABLED - _FORCE_INLINE_ FontGlyph rasterize_msdf(FontDataFallback *p_font_data, FontDataForSizeFallback *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const; + _FORCE_INLINE_ FontGlyph rasterize_msdf(FontFallback *p_font_data, FontForSizeFallback *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const; #endif #ifdef MODULE_FREETYPE_ENABLED - _FORCE_INLINE_ FontGlyph rasterize_bitmap(FontDataForSizeFallback *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const; + _FORCE_INLINE_ FontGlyph rasterize_bitmap(FontForSizeFallback *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const; #endif - _FORCE_INLINE_ bool _ensure_glyph(FontDataFallback *p_font_data, const Vector2i &p_size, int32_t p_glyph) const; - _FORCE_INLINE_ bool _ensure_cache_for_size(FontDataFallback *p_font_data, const Vector2i &p_size) const; - _FORCE_INLINE_ void _font_clear_cache(FontDataFallback *p_font_data); + _FORCE_INLINE_ bool _ensure_glyph(FontFallback *p_font_data, const Vector2i &p_size, int32_t p_glyph) const; + _FORCE_INLINE_ bool _ensure_cache_for_size(FontFallback *p_font_data, const Vector2i &p_size) const; + _FORCE_INLINE_ void _font_clear_cache(FontFallback *p_font_data); void _generateMTSDF_threaded(uint32_t y, void *p_td) const; - _FORCE_INLINE_ Vector2i _get_size(const FontDataFallback *p_font_data, int p_size) const { + _FORCE_INLINE_ Vector2i _get_size(const FontFallback *p_font_data, int p_size) const { if (p_font_data->msdf) { return Vector2i(p_font_data->msdf_source_size, 0); } else if (p_font_data->fixed_size > 0) { @@ -244,7 +238,7 @@ class TextServerFallback : public TextServerExtension { } } - _FORCE_INLINE_ Vector2i _get_size_outline(const FontDataFallback *p_font_data, const Vector2i &p_size) const { + _FORCE_INLINE_ Vector2i _get_size_outline(const FontFallback *p_font_data, const Vector2i &p_size) const { if (p_font_data->msdf) { return Vector2i(p_font_data->msdf_source_size, 0); } else if (p_font_data->fixed_size > 0) { @@ -312,6 +306,7 @@ class TextServerFallback : public TextServerExtension { double descent = 0.0; // Descent for horizontal layout, 1/2 of width for vertical. double width = 0.0; // Width for horizontal layout, height for vertical. double width_trimmed = 0.0; + int extra_spacing[4] = { 0, 0, 0, 0 }; double upos = 0.0; double uthk = 0.0; @@ -326,7 +321,7 @@ class TextServerFallback : public TextServerExtension { // Common data. double oversampling = 1.0; - mutable RID_PtrOwner<FontDataFallback> font_owner; + mutable RID_PtrOwner<FontFallback> font_owner; mutable RID_PtrOwner<ShapedTextDataFallback> shaped_owner; void _realign(ShapedTextDataFallback *p_sd) const; @@ -370,8 +365,8 @@ public: virtual int64_t font_get_face_count(const RID &p_font_rid) const override; - virtual void font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) override; - virtual int64_t /*FontStyle*/ font_get_style(const RID &p_font_rid) const override; + virtual void font_set_style(const RID &p_font_rid, BitField<FontStyle> p_style) override; + virtual BitField<FontStyle> font_get_style(const RID &p_font_rid) const override; virtual void font_set_style_name(const RID &p_font_rid, const String &p_name) override; virtual String font_get_style_name(const RID &p_font_rid) const override; @@ -437,9 +432,6 @@ public: virtual void font_set_scale(const RID &p_font_rid, int64_t p_size, double p_scale) override; virtual double font_get_scale(const RID &p_font_rid, int64_t p_size) const override; - virtual void font_set_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing, int64_t p_value) override; - virtual int64_t font_get_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing) const override; - virtual int64_t font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const override; virtual void font_clear_textures(const RID &p_font_rid, const Vector2i &p_size) override; virtual void font_remove_texture(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) override; @@ -536,6 +528,9 @@ public: virtual void shaped_text_set_preserve_control(const RID &p_shaped, bool p_enabled) override; virtual bool shaped_text_get_preserve_control(const RID &p_shaped) const override; + virtual void shaped_text_set_spacing(const RID &p_shaped, SpacingType p_spacing, int64_t p_value) override; + virtual int64_t shaped_text_get_spacing(const RID &p_shaped, SpacingType p_spacing) const override; + virtual bool shaped_text_add_string(const RID &p_shaped, const String &p_text, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) override; virtual bool shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int64_t p_length = 1) override; virtual bool shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER) override; @@ -547,7 +542,7 @@ public: virtual RID shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const override; virtual RID shaped_text_get_parent(const RID &p_shaped) const override; - virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override; + virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, BitField<TextServer::JustificationFlag> p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override; virtual double shaped_text_tab_align(const RID &p_shaped, const PackedFloat32Array &p_tab_stops) override; virtual bool shaped_text_shape(const RID &p_shaped) override; @@ -559,7 +554,7 @@ public: virtual const Glyph *shaped_text_get_ellipsis_glyphs(const RID &p_shaped) const override; virtual int64_t shaped_text_get_ellipsis_glyph_count(const RID &p_shaped) const override; - virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, int64_t p_trim_flags) override; + virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, BitField<TextServer::TextOverrunFlag> p_trim_flags) override; virtual bool shaped_text_is_ready(const RID &p_shaped) const override; @@ -588,4 +583,4 @@ public: ~TextServerFallback(); }; -#endif // TEXT_SERVER_FALLBACK_H +#endif // TEXT_SERVER_FB_H diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp index 77e370849f..c4462ba687 100644 --- a/modules/theora/video_stream_theora.cpp +++ b/modules/theora/video_stream_theora.cpp @@ -331,7 +331,7 @@ void VideoStreamPlaybackTheora::set_file(const String &p_file) { Ref<Image> img; img.instantiate(); img->create(w, h, false, Image::FORMAT_RGBA8); - texture->create_from_image(img); + texture->set_image(img); } else { /* tear down the partial theora setup */ diff --git a/modules/theora/video_stream_theora.h b/modules/theora/video_stream_theora.h index 8940ed6aff..00d799dc24 100644 --- a/modules/theora/video_stream_theora.h +++ b/modules/theora/video_stream_theora.h @@ -170,7 +170,7 @@ protected: static void _bind_methods(); public: - Ref<VideoStreamPlayback> instance_playback() override { + Ref<VideoStreamPlayback> instantiate_playback() override { Ref<VideoStreamPlaybackTheora> pb = memnew(VideoStreamPlaybackTheora); pb->set_audio_track(audio_track); pb->set_file(file); @@ -192,4 +192,4 @@ public: virtual String get_resource_type(const String &p_path) const; }; -#endif +#endif // VIDEO_STREAM_THEORA_H diff --git a/modules/tinyexr/image_loader_tinyexr.h b/modules/tinyexr/image_loader_tinyexr.h index c147861c26..0d3de93956 100644 --- a/modules/tinyexr/image_loader_tinyexr.h +++ b/modules/tinyexr/image_loader_tinyexr.h @@ -40,4 +40,4 @@ public: ImageLoaderTinyEXR(); }; -#endif +#endif // IMAGE_LOADER_TINYEXR_H diff --git a/modules/upnp/upnp.h b/modules/upnp/upnp.h index 6d87b42c56..be7ede3ee0 100644 --- a/modules/upnp/upnp.h +++ b/modules/upnp/upnp.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GODOT_UPNP_H -#define GODOT_UPNP_H +#ifndef UPNP_H +#define UPNP_H #include "core/object/ref_counted.h" @@ -121,4 +121,4 @@ public: VARIANT_ENUM_CAST(UPNP::UPNPResult) -#endif // GODOT_UPNP_H +#endif // UPNP_H diff --git a/modules/upnp/upnp_device.h b/modules/upnp/upnp_device.h index 18491dce27..1c9dc82df5 100644 --- a/modules/upnp/upnp_device.h +++ b/modules/upnp/upnp_device.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef GODOT_UPNP_DEVICE_H -#define GODOT_UPNP_DEVICE_H +#ifndef UPNP_DEVICE_H +#define UPNP_DEVICE_H #include "core/object/ref_counted.h" @@ -90,4 +90,4 @@ private: VARIANT_ENUM_CAST(UPNPDevice::IGDStatus) -#endif // GODOT_UPNP_DEVICE_H +#endif // UPNP_DEVICE_H diff --git a/modules/visual_script/editor/visual_script_editor.cpp b/modules/visual_script/editor/visual_script_editor.cpp index ceea0eaf1d..74a61bc4b7 100644 --- a/modules/visual_script/editor/visual_script_editor.cpp +++ b/modules/visual_script/editor/visual_script_editor.cpp @@ -376,6 +376,12 @@ static Color _color_from_type(Variant::Type p_type, bool dark_theme = true) { case Variant::VECTOR3I: color = Color(0.84, 0.49, 0.93); break; + case Variant::VECTOR4: + color = Color(0.84, 0.49, 0.94); + break; + case Variant::VECTOR4I: + color = Color(0.84, 0.49, 0.94); + break; case Variant::TRANSFORM2D: color = Color(0.77, 0.93, 0.41); break; @@ -1227,7 +1233,7 @@ void VisualScriptEditor::_member_selected() { selected = ti->get_metadata(0); if (ti->get_parent() == members->get_root()->get_first_child()) { -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED bool held_ctrl = Input::get_singleton()->is_key_pressed(Key::META); #else bool held_ctrl = Input::get_singleton()->is_key_pressed(Key::CTRL); @@ -2208,7 +2214,7 @@ bool VisualScriptEditor::can_drop_data_fw(const Point2 &p_point, const Variant & String(d["type"]) == "files" || String(d["type"]) == "nodes")) { if (String(d["type"]) == "obj_property") { -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED const_cast<VisualScriptEditor *>(this)->_show_hint(vformat(TTR("Hold %s to drop a Getter. Hold Shift to drop a generic signature."), find_keycode_name(Key::META))); #else const_cast<VisualScriptEditor *>(this)->_show_hint(TTR("Hold Ctrl to drop a Getter. Hold Shift to drop a generic signature.")); @@ -2216,7 +2222,7 @@ bool VisualScriptEditor::can_drop_data_fw(const Point2 &p_point, const Variant & } if (String(d["type"]) == "nodes") { -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED const_cast<VisualScriptEditor *>(this)->_show_hint(vformat(TTR("Hold %s to drop a simple reference to the node."), find_keycode_name(Key::META))); #else const_cast<VisualScriptEditor *>(this)->_show_hint(TTR("Hold Ctrl to drop a simple reference to the node.")); @@ -2224,7 +2230,7 @@ bool VisualScriptEditor::can_drop_data_fw(const Point2 &p_point, const Variant & } if (String(d["type"]) == "visual_script_variable_drag") { -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED const_cast<VisualScriptEditor *>(this)->_show_hint(vformat(TTR("Hold %s to drop a Variable Setter."), find_keycode_name(Key::META))); #else const_cast<VisualScriptEditor *>(this)->_show_hint(TTR("Hold Ctrl to drop a Variable Setter.")); @@ -2287,7 +2293,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da } if (String(d["type"]) == "visual_script_variable_drag") { -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED bool use_set = Input::get_singleton()->is_key_pressed(Key::META); #else bool use_set = Input::get_singleton()->is_key_pressed(Key::CTRL); @@ -2396,7 +2402,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da } if (String(d["type"]) == "files") { -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED bool use_preload = Input::get_singleton()->is_key_pressed(Key::META); #else bool use_preload = Input::get_singleton()->is_key_pressed(Key::CTRL); @@ -2459,7 +2465,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da return; } -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED bool use_node = Input::get_singleton()->is_key_pressed(Key::META); #else bool use_node = Input::get_singleton()->is_key_pressed(Key::CTRL); @@ -2524,7 +2530,7 @@ void VisualScriptEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da Node *node = Object::cast_to<Node>(obj); Vector2 pos = _get_pos_in_graph(p_point); -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED bool use_get = Input::get_singleton()->is_key_pressed(Key::META); #else bool use_get = Input::get_singleton()->is_key_pressed(Key::CTRL); @@ -3378,7 +3384,7 @@ void VisualScriptEditor::connect_data(Ref<VisualScriptNode> vnode_old, Ref<Visua } void VisualScriptEditor::_selected_connect_node(const String &p_text, const String &p_category, const bool p_connecting) { -#ifdef OSX_ENABLED +#ifdef MACOS_ENABLED bool held_ctrl = Input::get_singleton()->is_key_pressed(Key::META); #else bool held_ctrl = Input::get_singleton()->is_key_pressed(Key::CTRL); @@ -4628,7 +4634,7 @@ VisualScriptEditor::VisualScriptEditor() { graph = memnew(GraphEdit); add_child(graph); graph->set_v_size_flags(Control::SIZE_EXPAND_FILL); - graph->set_anchors_and_offsets_preset(Control::PRESET_WIDE); + graph->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); graph->set_show_zoom_label(true); graph->connect("node_selected", callable_mp(this, &VisualScriptEditor::_node_selected)); graph->connect("begin_node_move", callable_mp(this, &VisualScriptEditor::_begin_node_move)); @@ -4717,7 +4723,7 @@ VisualScriptEditor::VisualScriptEditor() { function_create_dialog = memnew(ConfirmationDialog); function_create_dialog->set_title(TTR("Create Function")); function_create_dialog->add_child(function_vb); - function_create_dialog->get_ok_button()->set_text(TTR("Create")); + function_create_dialog->set_ok_button_text(TTR("Create")); function_create_dialog->get_ok_button()->connect("pressed", callable_mp(this, &VisualScriptEditor::_create_function)); add_child(function_create_dialog); @@ -4761,7 +4767,7 @@ VisualScriptEditor::VisualScriptEditor() { graph->connect("connection_to_empty", callable_mp(this, &VisualScriptEditor::_graph_connect_to_empty)); edit_signal_dialog = memnew(AcceptDialog); - edit_signal_dialog->get_ok_button()->set_text(TTR("Close")); + edit_signal_dialog->set_ok_button_text(TTR("Close")); add_child(edit_signal_dialog); signal_editor = memnew(VisualScriptEditorSignalEdit); @@ -4771,7 +4777,7 @@ VisualScriptEditor::VisualScriptEditor() { edit_signal_edit->edit(signal_editor); edit_variable_dialog = memnew(AcceptDialog); - edit_variable_dialog->get_ok_button()->set_text(TTR("Close")); + edit_variable_dialog->set_ok_button_text(TTR("Close")); add_child(edit_variable_dialog); variable_editor = memnew(VisualScriptEditorVariableEdit); @@ -4821,12 +4827,15 @@ VisualScriptEditor::VisualScriptEditor() { base_type_map.insert("Rect2i", Variant::RECT2I); base_type_map.insert("Vector3", Variant::VECTOR3); base_type_map.insert("Vector3i", Variant::VECTOR3I); + base_type_map.insert("Vector4", Variant::VECTOR4); + base_type_map.insert("Vector4i", Variant::VECTOR4I); base_type_map.insert("Transform2D", Variant::TRANSFORM2D); base_type_map.insert("Plane", Variant::PLANE); base_type_map.insert("Quaternion", Variant::QUATERNION); base_type_map.insert("AABB", Variant::AABB); base_type_map.insert("Basis", Variant::BASIS); base_type_map.insert("Transform3D", Variant::TRANSFORM3D); + base_type_map.insert("Projection", Variant::PROJECTION); base_type_map.insert("Color", Variant::COLOR); base_type_map.insert("NodePath", Variant::NODE_PATH); base_type_map.insert("RID", Variant::RID); diff --git a/modules/visual_script/editor/visual_script_editor.h b/modules/visual_script/editor/visual_script_editor.h index fd59d22cbe..a6df7bba73 100644 --- a/modules/visual_script/editor/visual_script_editor.h +++ b/modules/visual_script/editor/visual_script_editor.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef VISUALSCRIPT_EDITOR_H -#define VISUALSCRIPT_EDITOR_H +#ifndef VISUAL_SCRIPT_EDITOR_H +#define VISUAL_SCRIPT_EDITOR_H #include "../visual_script.h" #include "editor/create_dialog.h" @@ -374,4 +374,4 @@ public: #endif -#endif // VISUALSCRIPT_EDITOR_H +#endif // VISUAL_SCRIPT_EDITOR_H diff --git a/modules/visual_script/editor/visual_script_property_selector.cpp b/modules/visual_script/editor/visual_script_property_selector.cpp index ae30655301..f98ce5bb26 100644 --- a/modules/visual_script/editor/visual_script_property_selector.cpp +++ b/modules/visual_script/editor/visual_script_property_selector.cpp @@ -533,7 +533,7 @@ VisualScriptPropertySelector::VisualScriptPropertySelector() { scroller->add_child(help_bit); help_bit->connect("request_hide", callable_mp(this, &VisualScriptPropertySelector::_hide_requested)); - get_ok_button()->set_text(TTR("Open")); + set_ok_button_text(TTR("Open")); get_ok_button()->set_disabled(true); set_hide_on_ok(false); } diff --git a/modules/visual_script/editor/visual_script_property_selector.h b/modules/visual_script/editor/visual_script_property_selector.h index 91d81bba47..41f8eea735 100644 --- a/modules/visual_script/editor/visual_script_property_selector.h +++ b/modules/visual_script/editor/visual_script_property_selector.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef VISUALSCRIPT_PROPERTYSELECTOR_H -#define VISUALSCRIPT_PROPERTYSELECTOR_H +#ifndef VISUAL_SCRIPT_PROPERTY_SELECTOR_H +#define VISUAL_SCRIPT_PROPERTY_SELECTOR_H #include "../visual_script.h" #include "editor/editor_help.h" @@ -226,4 +226,4 @@ public: SearchRunner(VisualScriptPropertySelector *p_selector_ui, Tree *p_results_tree); }; -#endif // VISUALSCRIPT_PROPERTYSELECTOR_H +#endif // VISUAL_SCRIPT_PROPERTY_SELECTOR_H diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index c5bcf23c8e..742fa75bb7 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -2435,6 +2435,9 @@ void VisualScriptLanguage::get_public_functions(List<MethodInfo> *p_functions) c void VisualScriptLanguage::get_public_constants(List<Pair<String, Variant>> *p_constants) const { } +void VisualScriptLanguage::get_public_annotations(List<MethodInfo> *p_annotations) const { +} + void VisualScriptLanguage::profiling_start() { } diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h index c2e4d0e597..716310f59b 100644 --- a/modules/visual_script/visual_script.h +++ b/modules/visual_script/visual_script.h @@ -599,6 +599,7 @@ public: virtual void get_recognized_extensions(List<String> *p_extensions) const override; virtual void get_public_functions(List<MethodInfo> *p_functions) const override; virtual void get_public_constants(List<Pair<String, Variant>> *p_constants) const override; + virtual void get_public_annotations(List<MethodInfo> *p_annotations) const override; virtual void profiling_start() override; virtual void profiling_stop() override; diff --git a/modules/visual_script/visual_script_expression.h b/modules/visual_script/visual_script_expression.h index c93eb0686b..7e10f98f36 100644 --- a/modules/visual_script/visual_script_expression.h +++ b/modules/visual_script/visual_script_expression.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef VISUALSCRIPTEXPRESSION_H -#define VISUALSCRIPTEXPRESSION_H +#ifndef VISUAL_SCRIPT_EXPRESSION_H +#define VISUAL_SCRIPT_EXPRESSION_H #include "visual_script.h" #include "visual_script_builtin_funcs.h" @@ -281,4 +281,4 @@ public: void register_visual_script_expression_node(); -#endif // VISUALSCRIPTEXPRESSION_H +#endif // VISUAL_SCRIPT_EXPRESSION_H diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index 2dfc6da181..41f5b28677 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -4025,6 +4025,8 @@ void register_visual_script_nodes() { VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR2I), create_node_deconst_typed<Variant::Type::VECTOR2I>); VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR3), create_node_deconst_typed<Variant::Type::VECTOR3>); VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR3I), create_node_deconst_typed<Variant::Type::VECTOR3I>); + VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR4), create_node_deconst_typed<Variant::Type::VECTOR4>); + VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::VECTOR4I), create_node_deconst_typed<Variant::Type::VECTOR4I>); VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::COLOR), create_node_deconst_typed<Variant::Type::COLOR>); VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::RECT2), create_node_deconst_typed<Variant::Type::RECT2>); VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::RECT2I), create_node_deconst_typed<Variant::Type::RECT2I>); @@ -4034,6 +4036,7 @@ void register_visual_script_nodes() { VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::AABB), create_node_deconst_typed<Variant::Type::AABB>); VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::BASIS), create_node_deconst_typed<Variant::Type::BASIS>); VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::TRANSFORM3D), create_node_deconst_typed<Variant::Type::TRANSFORM3D>); + VisualScriptLanguage::singleton->add_register_func("functions/deconstruct/" + Variant::get_type_name(Variant::Type::PROJECTION), create_node_deconst_typed<Variant::Type::PROJECTION>); VisualScriptLanguage::singleton->add_register_func("functions/compose_array", create_node_generic<VisualScriptComposeArray>); for (int i = 1; i < Variant::VARIANT_MAX; i++) { diff --git a/modules/vorbis/audio_stream_ogg_vorbis.cpp b/modules/vorbis/audio_stream_ogg_vorbis.cpp index 89a6b03ff8..76f7317daa 100644 --- a/modules/vorbis/audio_stream_ogg_vorbis.cpp +++ b/modules/vorbis/audio_stream_ogg_vorbis.cpp @@ -43,28 +43,93 @@ int AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_fram int todo = p_frames; - int start_buffer = 0; + int beat_length_frames = -1; + bool beat_loop = vorbis_stream->has_loop(); + if (beat_loop && vorbis_stream->get_bpm() > 0 && vorbis_stream->get_beat_count() > 0) { + beat_length_frames = vorbis_stream->get_beat_count() * vorbis_data->get_sampling_rate() * 60 / vorbis_stream->get_bpm(); + } while (todo > 0 && active) { AudioFrame *buffer = p_buffer; - if (start_buffer > 0) { - buffer = buffer + start_buffer; + buffer += p_frames - todo; + + int to_mix = todo; + if (beat_length_frames >= 0 && (beat_length_frames - (int)frames_mixed) < to_mix) { + to_mix = MAX(0, beat_length_frames - (int)frames_mixed); } - int mixed = _mix_frames_vorbis(buffer, todo); + + int mixed = _mix_frames_vorbis(buffer, to_mix); ERR_FAIL_COND_V(mixed < 0, 0); todo -= mixed; frames_mixed += mixed; - start_buffer += mixed; + + if (loop_fade_remaining < FADE_SIZE) { + int to_fade = loop_fade_remaining + MIN(FADE_SIZE - loop_fade_remaining, mixed); + for (int i = loop_fade_remaining; i < to_fade; i++) { + buffer[i - loop_fade_remaining] += loop_fade[i] * (float(FADE_SIZE - i) / float(FADE_SIZE)); + } + loop_fade_remaining = to_fade; + } + + if (beat_length_frames >= 0) { + /** + * Length determined by beat length + * This code is commented out because, in practice, it is prefered that the fade + * is done by the transitioner and this stream just goes on until it ends while fading out. + * + * End fade implementation is left here for reference in case at some point this feature + * is desired. + + if (!beat_loop && (int)frames_mixed > beat_length_frames - FADE_SIZE) { + print_line("beat length fade/after mix?"); + //No loop, just fade and finish + for (int i = 0; i < mixed; i++) { + int idx = frames_mixed + i - mixed; + buffer[i] *= 1.0 - float(MAX(0, (idx - (beat_length_frames - FADE_SIZE)))) / float(FADE_SIZE); + } + if ((int)frames_mixed == beat_length_frames) { + for (int i = p_frames - todo; i < p_frames; i++) { + p_buffer[i] = AudioFrame(0, 0); + } + active = false; + break; + } + } else + **/ + + if (beat_loop && beat_length_frames <= (int)frames_mixed) { + // End of file when doing beat-based looping. <= used instead of == because importer editing + if (!have_packets_left && !have_samples_left) { + //Nothing remaining, so do nothing. + loop_fade_remaining = FADE_SIZE; + } else { + // Add some loop fade; + int faded_mix = _mix_frames_vorbis(loop_fade, FADE_SIZE); + + for (int i = faded_mix; i < FADE_SIZE; i++) { + // In case lesss was mixed, pad with zeros + loop_fade[i] = AudioFrame(0, 0); + } + loop_fade_remaining = 0; + } + + seek(vorbis_stream->loop_offset); + loops++; + // We still have buffer to fill, start from this element in the next iteration. + continue; + } + } + if (!have_packets_left && !have_samples_left) { - //end of file! + // Actual end of file! bool is_not_empty = mixed > 0 || vorbis_stream->get_length() > 0; if (vorbis_stream->loop && is_not_empty) { //loop seek(vorbis_stream->loop_offset); loops++; - // we still have buffer to fill, start from this element in the next iteration. - start_buffer = p_frames - todo; + // We still have buffer to fill, start from this element in the next iteration. + } else { for (int i = p_frames - todo; i < p_frames; i++) { p_buffer[i] = AudioFrame(0, 0); @@ -130,7 +195,7 @@ bool AudioStreamPlaybackOGGVorbis::_alloc_vorbis() { comment_is_allocated = true; ERR_FAIL_COND_V(vorbis_data.is_null(), false); - vorbis_data_playback = vorbis_data->instance_playback(); + vorbis_data_playback = vorbis_data->instantiate_playback(); ogg_packet *packet; int err; @@ -160,6 +225,7 @@ bool AudioStreamPlaybackOGGVorbis::_alloc_vorbis() { void AudioStreamPlaybackOGGVorbis::start(float p_from_pos) { ERR_FAIL_COND(!ready); + loop_fade_remaining = FADE_SIZE; active = true; seek(p_from_pos); loops = 0; @@ -182,6 +248,10 @@ float AudioStreamPlaybackOGGVorbis::get_playback_position() const { return float(frames_mixed) / vorbis_data->get_sampling_rate(); } +void AudioStreamPlaybackOGGVorbis::tag_used_streams() { + vorbis_stream->tag_used(get_playback_position()); +} + void AudioStreamPlaybackOGGVorbis::seek(float p_time) { ERR_FAIL_COND(!ready); ERR_FAIL_COND(vorbis_stream.is_null()); @@ -315,7 +385,7 @@ AudioStreamPlaybackOGGVorbis::~AudioStreamPlaybackOGGVorbis() { } } -Ref<AudioStreamPlayback> AudioStreamOGGVorbis::instance_playback() { +Ref<AudioStreamPlayback> AudioStreamOGGVorbis::instantiate_playback() { Ref<AudioStreamPlaybackOGGVorbis> ovs; ERR_FAIL_COND_V(packet_sequence.is_null(), nullptr); @@ -347,7 +417,7 @@ void AudioStreamOGGVorbis::maybe_update_info() { vorbis_info_init(&info); vorbis_comment_init(&comment); - Ref<OGGPacketSequencePlayback> packet_sequence_playback = packet_sequence->instance_playback(); + Ref<OGGPacketSequencePlayback> packet_sequence_playback = packet_sequence->instantiate_playback(); for (int i = 0; i < 3; i++) { ogg_packet *packet; @@ -405,6 +475,36 @@ float AudioStreamOGGVorbis::get_length() const { return packet_sequence->get_length(); } +void AudioStreamOGGVorbis::set_bpm(double p_bpm) { + ERR_FAIL_COND(p_bpm < 0); + bpm = p_bpm; + emit_changed(); +} + +double AudioStreamOGGVorbis::get_bpm() const { + return bpm; +} + +void AudioStreamOGGVorbis::set_beat_count(int p_beat_count) { + ERR_FAIL_COND(p_beat_count < 0); + beat_count = p_beat_count; + emit_changed(); +} + +int AudioStreamOGGVorbis::get_beat_count() const { + return beat_count; +} + +void AudioStreamOGGVorbis::set_bar_beats(int p_bar_beats) { + ERR_FAIL_COND(p_bar_beats < 2); + bar_beats = p_bar_beats; + emit_changed(); +} + +int AudioStreamOGGVorbis::get_bar_beats() const { + return bar_beats; +} + bool AudioStreamOGGVorbis::is_monophonic() const { return false; } @@ -419,7 +519,19 @@ void AudioStreamOGGVorbis::_bind_methods() { ClassDB::bind_method(D_METHOD("set_loop_offset", "seconds"), &AudioStreamOGGVorbis::set_loop_offset); ClassDB::bind_method(D_METHOD("get_loop_offset"), &AudioStreamOGGVorbis::get_loop_offset); + ClassDB::bind_method(D_METHOD("set_bpm", "bpm"), &AudioStreamOGGVorbis::set_bpm); + ClassDB::bind_method(D_METHOD("get_bpm"), &AudioStreamOGGVorbis::get_bpm); + + ClassDB::bind_method(D_METHOD("set_beat_count", "count"), &AudioStreamOGGVorbis::set_beat_count); + ClassDB::bind_method(D_METHOD("get_beat_count"), &AudioStreamOGGVorbis::get_beat_count); + + ClassDB::bind_method(D_METHOD("set_bar_beats", "count"), &AudioStreamOGGVorbis::set_bar_beats); + ClassDB::bind_method(D_METHOD("get_bar_beats"), &AudioStreamOGGVorbis::get_bar_beats); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "packet_sequence", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_packet_sequence", "get_packet_sequence"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bpm", PROPERTY_HINT_RANGE, "0,400,0.01,or_greater"), "set_bpm", "get_bpm"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "beat_count", PROPERTY_HINT_RANGE, "0,512,1,or_greater"), "set_beat_count", "get_beat_count"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "bar_beats", PROPERTY_HINT_RANGE, "2,32,1,or_greater"), "set_bar_beats", "get_bar_beats"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "loop_offset"), "set_loop_offset", "get_loop_offset"); } diff --git a/modules/vorbis/audio_stream_ogg_vorbis.h b/modules/vorbis/audio_stream_ogg_vorbis.h index b09ef9ff5d..9b6d928d87 100644 --- a/modules/vorbis/audio_stream_ogg_vorbis.h +++ b/modules/vorbis/audio_stream_ogg_vorbis.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef AUDIO_STREAM_LIBVORBIS_H -#define AUDIO_STREAM_LIBVORBIS_H +#ifndef AUDIO_STREAM_OGG_VORBIS_H +#define AUDIO_STREAM_OGG_VORBIS_H #include "core/variant/variant.h" #include "modules/ogg/ogg_packet_sequence.h" @@ -45,6 +45,12 @@ class AudioStreamPlaybackOGGVorbis : public AudioStreamPlaybackResampled { bool active = false; int loops = 0; + enum { + FADE_SIZE = 256 + }; + AudioFrame loop_fade[FADE_SIZE]; + int loop_fade_remaining = FADE_SIZE; + vorbis_info info; vorbis_comment comment; vorbis_dsp_state dsp_state; @@ -66,6 +72,7 @@ class AudioStreamPlaybackOGGVorbis : public AudioStreamPlaybackResampled { Ref<OGGPacketSequencePlayback> vorbis_data_playback; Ref<AudioStreamOGGVorbis> vorbis_stream; + int _mix_frames(AudioFrame *p_buffer, int p_frames); int _mix_frames_vorbis(AudioFrame *p_buffer, int p_frames); // Allocates vorbis data structures. Returns true upon success, false on failure. @@ -85,6 +92,8 @@ public: virtual float get_playback_position() const override; virtual void seek(float p_time) override; + virtual void tag_used_streams() override; + AudioStreamPlaybackOGGVorbis() {} ~AudioStreamPlaybackOGGVorbis(); }; @@ -107,17 +116,30 @@ class AudioStreamOGGVorbis : public AudioStream { Ref<OGGPacketSequence> packet_sequence; + double bpm = 0; + int beat_count = 0; + int bar_beats = 4; + protected: static void _bind_methods(); public: void set_loop(bool p_enable); - bool has_loop() const; + virtual bool has_loop() const override; void set_loop_offset(float p_seconds); float get_loop_offset() const; - virtual Ref<AudioStreamPlayback> instance_playback() override; + void set_bpm(double p_bpm); + virtual double get_bpm() const override; + + void set_beat_count(int p_beat_count); + virtual int get_beat_count() const override; + + void set_bar_beats(int p_bar_beats); + virtual int get_bar_beats() const override; + + virtual Ref<AudioStreamPlayback> instantiate_playback() override; virtual String get_stream_name() const override; void set_packet_sequence(Ref<OGGPacketSequence> p_packet_sequence); @@ -131,4 +153,4 @@ public: virtual ~AudioStreamOGGVorbis(); }; -#endif // AUDIO_STREAM_LIBVORBIS_H +#endif // AUDIO_STREAM_OGG_VORBIS_H diff --git a/modules/vorbis/doc_classes/AudioStreamOGGVorbis.xml b/modules/vorbis/doc_classes/AudioStreamOGGVorbis.xml index 2f210a6cb4..f87296dcd8 100644 --- a/modules/vorbis/doc_classes/AudioStreamOGGVorbis.xml +++ b/modules/vorbis/doc_classes/AudioStreamOGGVorbis.xml @@ -7,6 +7,12 @@ <tutorials> </tutorials> <members> + <member name="bar_beats" type="int" setter="set_bar_beats" getter="get_bar_beats" default="4"> + </member> + <member name="beat_count" type="int" setter="set_beat_count" getter="get_beat_count" default="0"> + </member> + <member name="bpm" type="float" setter="set_bpm" getter="get_bpm" default="0.0"> + </member> <member name="loop" type="bool" setter="set_loop" getter="has_loop" default="false"> If [code]true[/code], the stream will automatically loop when it reaches the end. </member> diff --git a/modules/vorbis/resource_importer_ogg_vorbis.cpp b/modules/vorbis/resource_importer_ogg_vorbis.cpp index 7ee6446313..9461d531fd 100644 --- a/modules/vorbis/resource_importer_ogg_vorbis.cpp +++ b/modules/vorbis/resource_importer_ogg_vorbis.cpp @@ -30,13 +30,16 @@ #include "resource_importer_ogg_vorbis.h" -#include "audio_stream_ogg_vorbis.h" #include "core/io/file_access.h" #include "core/io/resource_saver.h" #include "scene/resources/texture.h" #include "thirdparty/libogg/ogg/ogg.h" #include "thirdparty/libvorbis/vorbis/codec.h" +#ifdef TOOLS_ENABLED +#include "editor/import/audio_stream_import_settings.h" +#endif + String ResourceImporterOGGVorbis::get_importer_name() const { return "oggvorbisstr"; } @@ -72,14 +75,14 @@ String ResourceImporterOGGVorbis::get_preset_name(int p_idx) const { void ResourceImporterOGGVorbis::get_import_options(const String &p_path, List<ImportOption> *r_options, int p_preset) const { r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "loop"), true)); r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "loop_offset"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::FLOAT, "bpm", PROPERTY_HINT_RANGE, "0,400,0.01,or_greater"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "beat_count", PROPERTY_HINT_RANGE, "0,512,or_greater"), 0)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "bar_beats", PROPERTY_HINT_RANGE, "2,32,or_greater"), 4)); } -Error ResourceImporterOGGVorbis::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { - bool loop = p_options["loop"]; - float loop_offset = p_options["loop_offset"]; - - Ref<FileAccess> f = FileAccess::open(p_source_file, FileAccess::READ); - ERR_FAIL_COND_V_MSG(f.is_null(), ERR_CANT_OPEN, "Cannot open file '" + p_source_file + "'."); +Ref<AudioStreamOGGVorbis> ResourceImporterOGGVorbis::import_ogg_vorbis(const String &p_path) { + Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ); + ERR_FAIL_COND_V_MSG(f.is_null(), Ref<AudioStreamOGGVorbis>(), "Cannot open file '" + p_path + "'."); uint64_t len = f->get_length(); @@ -107,16 +110,16 @@ Error ResourceImporterOGGVorbis::import(const String &p_source_file, const Strin size_t packet_count = 0; bool done = false; while (!done) { - ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Error::ERR_INVALID_DATA, "Ogg sync error " + itos(err)); + ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOGGVorbis>(), "Ogg sync error " + itos(err)); while (ogg_sync_pageout(&sync_state, &page) != 1) { if (cursor >= len) { done = true; break; } - ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Error::ERR_INVALID_DATA, "Ogg sync error " + itos(err)); + ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOGGVorbis>(), "Ogg sync error " + itos(err)); char *sync_buf = ogg_sync_buffer(&sync_state, OGG_SYNC_BUFFER_SIZE); - ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Error::ERR_INVALID_DATA, "Ogg sync error " + itos(err)); - ERR_FAIL_COND_V(cursor > len, Error::ERR_INVALID_DATA); + ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOGGVorbis>(), "Ogg sync error " + itos(err)); + ERR_FAIL_COND_V(cursor > len, Ref<AudioStreamOGGVorbis>()); size_t copy_size = len - cursor; if (copy_size > OGG_SYNC_BUFFER_SIZE) { copy_size = OGG_SYNC_BUFFER_SIZE; @@ -124,22 +127,22 @@ Error ResourceImporterOGGVorbis::import(const String &p_source_file, const Strin memcpy(sync_buf, &file_data[cursor], copy_size); ogg_sync_wrote(&sync_state, copy_size); cursor += copy_size; - ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Error::ERR_INVALID_DATA, "Ogg sync error " + itos(err)); + ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOGGVorbis>(), "Ogg sync error " + itos(err)); } if (done) { break; } - ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Error::ERR_INVALID_DATA, "Ogg sync error " + itos(err)); + ERR_FAIL_COND_V_MSG((err = ogg_sync_check(&sync_state)), Ref<AudioStreamOGGVorbis>(), "Ogg sync error " + itos(err)); // Have a page now. if (!initialized_stream) { if (ogg_stream_init(&stream_state, ogg_page_serialno(&page))) { - ERR_FAIL_V_MSG(Error::ERR_OUT_OF_MEMORY, "Failed allocating memory for OGG Vorbis stream."); + ERR_FAIL_V_MSG(Ref<AudioStreamOGGVorbis>(), "Failed allocating memory for OGG Vorbis stream."); } initialized_stream = true; } ogg_stream_pagein(&stream_state, &page); - ERR_FAIL_COND_V_MSG((err = ogg_stream_check(&stream_state)), Error::ERR_INVALID_DATA, "Ogg stream error " + itos(err)); + ERR_FAIL_COND_V_MSG((err = ogg_stream_check(&stream_state)), Ref<AudioStreamOGGVorbis>(), "Ogg stream error " + itos(err)); int desync_iters = 0; Vector<Vector<uint8_t>> packet_data; @@ -150,7 +153,7 @@ Error ResourceImporterOGGVorbis::import(const String &p_source_file, const Strin if (err == -1) { // According to the docs this is usually recoverable, but don't sit here spinning forever. desync_iters++; - ERR_FAIL_COND_V_MSG(desync_iters > 100, Error::ERR_INVALID_DATA, "Packet sync issue during ogg import"); + ERR_FAIL_COND_V_MSG(desync_iters > 100, Ref<AudioStreamOGGVorbis>(), "Packet sync issue during ogg import"); continue; } else if (err == 0) { // Not enough data to fully reconstruct a packet. Go on to the next page. @@ -183,12 +186,45 @@ Error ResourceImporterOGGVorbis::import(const String &p_source_file, const Strin ogg_sync_clear(&sync_state); if (ogg_packet_sequence->get_packet_granule_positions().is_empty()) { - ERR_FAIL_V_MSG(Error::ERR_FILE_CORRUPT, "OGG Vorbis decoding failed. Check that your data is a valid OGG Vorbis audio stream."); + ERR_FAIL_V_MSG(Ref<AudioStreamOGGVorbis>(), "OGG Vorbis decoding failed. Check that your data is a valid OGG Vorbis audio stream."); } ogg_vorbis_stream->set_packet_sequence(ogg_packet_sequence); + + return ogg_vorbis_stream; +} + +#ifdef TOOLS_ENABLED + +bool ResourceImporterOGGVorbis::has_advanced_options() const { + return true; +} + +void ResourceImporterOGGVorbis::show_advanced_options(const String &p_path) { + Ref<AudioStreamOGGVorbis> ogg_stream = import_ogg_vorbis(p_path); + if (ogg_stream.is_valid()) { + AudioStreamImportSettings::get_singleton()->edit(p_path, "oggvorbisstr", ogg_stream); + } +} +#endif + +Error ResourceImporterOGGVorbis::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { + bool loop = p_options["loop"]; + float loop_offset = p_options["loop_offset"]; + double bpm = p_options["bpm"]; + int beat_count = p_options["beat_count"]; + int bar_beats = p_options["bar_beats"]; + + Ref<AudioStreamOGGVorbis> ogg_vorbis_stream = import_ogg_vorbis(p_source_file); + if (ogg_vorbis_stream.is_null()) { + return ERR_CANT_OPEN; + } + ogg_vorbis_stream->set_loop(loop); ogg_vorbis_stream->set_loop_offset(loop_offset); + ogg_vorbis_stream->set_bpm(bpm); + ogg_vorbis_stream->set_beat_count(beat_count); + ogg_vorbis_stream->set_bar_beats(bar_beats); return ResourceSaver::save(p_save_path + ".oggvorbisstr", ogg_vorbis_stream); } diff --git a/modules/vorbis/resource_importer_ogg_vorbis.h b/modules/vorbis/resource_importer_ogg_vorbis.h index 3b4a68a1fd..e6e98a29c1 100644 --- a/modules/vorbis/resource_importer_ogg_vorbis.h +++ b/modules/vorbis/resource_importer_ogg_vorbis.h @@ -31,6 +31,7 @@ #ifndef RESOURCE_IMPORTER_OGG_VORBIS_H #define RESOURCE_IMPORTER_OGG_VORBIS_H +#include "audio_stream_ogg_vorbis.h" #include "core/io/resource_importer.h" class ResourceImporterOGGVorbis : public ResourceImporter { @@ -43,7 +44,13 @@ class ResourceImporterOGGVorbis : public ResourceImporter { private: // virtual int get_samples_in_packet(Vector<uint8_t> p_packet) = 0; + static Ref<AudioStreamOGGVorbis> import_ogg_vorbis(const String &p_path); + public: +#ifdef TOOLS_ENABLED + virtual bool has_advanced_options() const override; + virtual void show_advanced_options(const String &p_path) override; +#endif virtual void get_recognized_extensions(List<String> *p_extensions) const override; virtual String get_save_extension() const override; virtual String get_resource_type() const override; diff --git a/modules/webp/image_loader_webp.h b/modules/webp/image_loader_webp.h index 448f683eb3..9a5dc6cd7c 100644 --- a/modules/webp/image_loader_webp.h +++ b/modules/webp/image_loader_webp.h @@ -40,4 +40,4 @@ public: ImageLoaderWebP(); }; -#endif +#endif // IMAGE_LOADER_WEBP_H diff --git a/modules/webrtc/webrtc_data_channel.h b/modules/webrtc/webrtc_data_channel.h index 75e29283ec..9d20ad3266 100644 --- a/modules/webrtc/webrtc_data_channel.h +++ b/modules/webrtc/webrtc_data_channel.h @@ -81,4 +81,5 @@ public: VARIANT_ENUM_CAST(WebRTCDataChannel::WriteMode); VARIANT_ENUM_CAST(WebRTCDataChannel::ChannelState); + #endif // WEBRTC_DATA_CHANNEL_H diff --git a/modules/webrtc/webrtc_multiplayer_peer.h b/modules/webrtc/webrtc_multiplayer_peer.h index 97550a3e9d..d4ed7ef7de 100644 --- a/modules/webrtc/webrtc_multiplayer_peer.h +++ b/modules/webrtc/webrtc_multiplayer_peer.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef WEBRTC_MULTIPLAYER_H -#define WEBRTC_MULTIPLAYER_H +#ifndef WEBRTC_MULTIPLAYER_PEER_H +#define WEBRTC_MULTIPLAYER_PEER_H #include "core/multiplayer/multiplayer_peer.h" #include "webrtc_peer_connection.h" @@ -106,4 +106,4 @@ public: ConnectionStatus get_connection_status() const override; }; -#endif // WEBRTC_MULTIPLAYER_H +#endif // WEBRTC_MULTIPLAYER_PEER_H diff --git a/modules/webrtc/webrtc_peer_connection.h b/modules/webrtc/webrtc_peer_connection.h index 8c324d0942..122ea3d00f 100644 --- a/modules/webrtc/webrtc_peer_connection.h +++ b/modules/webrtc/webrtc_peer_connection.h @@ -74,4 +74,5 @@ public: }; VARIANT_ENUM_CAST(WebRTCPeerConnection::ConnectionState); + #endif // WEBRTC_PEER_CONNECTION_H diff --git a/modules/webrtc/webrtc_peer_connection_js.cpp b/modules/webrtc/webrtc_peer_connection_js.cpp index 90e19fe4f1..ee3a302fa2 100644 --- a/modules/webrtc/webrtc_peer_connection_js.cpp +++ b/modules/webrtc/webrtc_peer_connection_js.cpp @@ -57,7 +57,7 @@ void WebRTCPeerConnectionJS::_on_error(void *p_obj) { void WebRTCPeerConnectionJS::_on_data_channel(void *p_obj, int p_id) { WebRTCPeerConnectionJS *peer = static_cast<WebRTCPeerConnectionJS *>(p_obj); - peer->emit_signal(SNAME("data_channel_received"), Ref<WebRTCDataChannelJS>(new WebRTCDataChannelJS(p_id))); + peer->emit_signal(SNAME("data_channel_received"), Ref<WebRTCDataChannel>(memnew(WebRTCDataChannelJS(p_id)))); } void WebRTCPeerConnectionJS::close() { diff --git a/modules/webrtc/webrtc_peer_connection_js.h b/modules/webrtc/webrtc_peer_connection_js.h index 8fa5ea7779..76b8c7fff8 100644 --- a/modules/webrtc/webrtc_peer_connection_js.h +++ b/modules/webrtc/webrtc_peer_connection_js.h @@ -52,6 +52,8 @@ extern int godot_js_rtc_pc_datachannel_create(int p_id, const char *p_label, con } class WebRTCPeerConnectionJS : public WebRTCPeerConnection { + GDCLASS(WebRTCPeerConnectionJS, WebRTCPeerConnection); + private: int _js_id; ConnectionState _conn_state; diff --git a/modules/websocket/emws_client.h b/modules/websocket/emws_client.h index ca327a56fa..b71fd78124 100644 --- a/modules/websocket/emws_client.h +++ b/modules/websocket/emws_client.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef EMWSCLIENT_H -#define EMWSCLIENT_H +#ifndef EMWS_CLIENT_H +#define EMWS_CLIENT_H #ifdef JAVASCRIPT_ENABLED @@ -68,4 +68,4 @@ public: #endif // JAVASCRIPT_ENABLED -#endif // EMWSCLIENT_H +#endif // EMWS_CLIENT_H diff --git a/modules/websocket/emws_peer.h b/modules/websocket/emws_peer.h index 6bb4552c37..f52f615c35 100644 --- a/modules/websocket/emws_peer.h +++ b/modules/websocket/emws_peer.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef EMWSPEER_H -#define EMWSPEER_H +#ifndef EMWS_PEER_H +#define EMWS_PEER_H #ifdef JAVASCRIPT_ENABLED @@ -90,4 +90,4 @@ public: #endif // JAVASCRIPT_ENABLED -#endif // LSWPEER_H +#endif // EMWS_PEER_H diff --git a/modules/websocket/emws_server.h b/modules/websocket/emws_server.h index ae31d9dbb0..14a9449605 100644 --- a/modules/websocket/emws_server.h +++ b/modules/websocket/emws_server.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef EMWSSERVER_H -#define EMWSSERVER_H +#ifndef EMWS_SERVER_H +#define EMWS_SERVER_H #ifdef JAVASCRIPT_ENABLED @@ -61,4 +61,4 @@ public: #endif -#endif // LWSSERVER_H +#endif // EMWS_SERVER_H diff --git a/modules/websocket/websocket_peer.h b/modules/websocket/websocket_peer.h index 13fef2424f..22099f7258 100644 --- a/modules/websocket/websocket_peer.h +++ b/modules/websocket/websocket_peer.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef WEBSOCKETPEER_H -#define WEBSOCKETPEER_H +#ifndef WEBSOCKET_PEER_H +#define WEBSOCKET_PEER_H #include "core/error/error_list.h" #include "core/io/packet_peer.h" @@ -66,4 +66,5 @@ public: }; VARIANT_ENUM_CAST(WebSocketPeer::WriteMode); -#endif // WEBSOCKETPEER_H + +#endif // WEBSOCKET_PEER_H diff --git a/modules/websocket/websocket_server.h b/modules/websocket/websocket_server.h index 7bd80851f5..ac04c4e57e 100644 --- a/modules/websocket/websocket_server.h +++ b/modules/websocket/websocket_server.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef WEBSOCKET_H -#define WEBSOCKET_H +#ifndef WEBSOCKET_SERVER_H +#define WEBSOCKET_SERVER_H #include "core/crypto/crypto.h" #include "core/object/ref_counted.h" @@ -87,4 +87,4 @@ public: ~WebSocketServer(); }; -#endif // WEBSOCKET_H +#endif // WEBSOCKET_SERVER_H diff --git a/modules/websocket/wsl_client.h b/modules/websocket/wsl_client.h index 22d7ffa839..58b867fbe4 100644 --- a/modules/websocket/wsl_client.h +++ b/modules/websocket/wsl_client.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef WSLCLIENT_H -#define WSLCLIENT_H +#ifndef WSL_CLIENT_H +#define WSL_CLIENT_H #ifndef JAVASCRIPT_ENABLED @@ -88,4 +88,4 @@ public: #endif // JAVASCRIPT_ENABLED -#endif // WSLCLIENT_H +#endif // WSL_CLIENT_H diff --git a/modules/websocket/wsl_peer.h b/modules/websocket/wsl_peer.h index abeecdd537..aabd3fd43e 100644 --- a/modules/websocket/wsl_peer.h +++ b/modules/websocket/wsl_peer.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef WSLPEER_H -#define WSLPEER_H +#ifndef WSL_PEER_H +#define WSL_PEER_H #ifndef JAVASCRIPT_ENABLED @@ -112,4 +112,4 @@ public: #endif // JAVASCRIPT_ENABLED -#endif // LSWPEER_H +#endif // WSL_PEER_H diff --git a/modules/websocket/wsl_server.h b/modules/websocket/wsl_server.h index a920e9c665..ec7567c732 100644 --- a/modules/websocket/wsl_server.h +++ b/modules/websocket/wsl_server.h @@ -28,8 +28,8 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef WSLSERVER_H -#define WSLSERVER_H +#ifndef WSL_SERVER_H +#define WSL_SERVER_H #ifndef JAVASCRIPT_ENABLED @@ -95,4 +95,4 @@ public: #endif // JAVASCRIPT_ENABLED -#endif // WSLSERVER_H +#endif // WSL_SERVER_H diff --git a/modules/webxr/godot_webxr.h b/modules/webxr/godot_webxr.h index 34225df001..52104895d4 100644 --- a/modules/webxr/godot_webxr.h +++ b/modules/webxr/godot_webxr.h @@ -82,4 +82,4 @@ extern int *godot_webxr_get_bounds_geometry(); } #endif -#endif /* GODOT_WEBXR_H */ +#endif // GODOT_WEBXR_H diff --git a/modules/webxr/webxr_interface_js.cpp b/modules/webxr/webxr_interface_js.cpp index 74e744402b..07e6760555 100644 --- a/modules/webxr/webxr_interface_js.cpp +++ b/modules/webxr/webxr_interface_js.cpp @@ -363,8 +363,8 @@ Transform3D WebXRInterfaceJS::get_transform_for_view(uint32_t p_view, const Tran return p_cam_transform * xr_server->get_reference_frame() * transform_for_eye; }; -CameraMatrix WebXRInterfaceJS::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) { - CameraMatrix eye; +Projection WebXRInterfaceJS::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) { + Projection eye; float *js_matrix = godot_webxr_get_projection_for_eye(p_view + 1); if (!initialized || js_matrix == nullptr) { diff --git a/modules/webxr/webxr_interface_js.h b/modules/webxr/webxr_interface_js.h index 31858194f6..f1ffedba46 100644 --- a/modules/webxr/webxr_interface_js.h +++ b/modules/webxr/webxr_interface_js.h @@ -87,7 +87,7 @@ public: virtual uint32_t get_view_count() override; virtual Transform3D get_camera_transform() override; virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override; - virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override; + virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override; virtual Vector<BlitToScreen> post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) override; virtual void process() override; |