diff options
18 files changed, 183 insertions, 34 deletions
diff --git a/core/extension/gdextension.cpp b/core/extension/gdextension.cpp index 3bc7dde10a..bffa0e251f 100644 --- a/core/extension/gdextension.cpp +++ b/core/extension/gdextension.cpp @@ -301,6 +301,8 @@ void GDExtension::_register_extension_class(GDExtensionClassLibraryPtr p_library p_extension_funcs->create_instance_func, // GDExtensionClassCreateInstance create_instance_func; /* this one is mandatory */ p_extension_funcs->free_instance_func, // GDExtensionClassFreeInstance free_instance_func; /* this one is mandatory */ p_extension_funcs->get_virtual_func, // GDExtensionClassGetVirtual get_virtual_func; + nullptr, // GDExtensionClassGetVirtualCallData get_virtual_call_data_func; + nullptr, // GDExtensionClassCallVirtualWithData call_virtual_func; p_extension_funcs->get_rid_func, // GDExtensionClassGetRID get_rid; p_extension_funcs->class_userdata, // void *class_userdata; }; @@ -375,6 +377,8 @@ void GDExtension::_register_extension_class_internal(GDExtensionClassLibraryPtr extension->gdextension.create_instance = p_extension_funcs->create_instance_func; extension->gdextension.free_instance = p_extension_funcs->free_instance_func; extension->gdextension.get_virtual = p_extension_funcs->get_virtual_func; + extension->gdextension.get_virtual_call_data = p_extension_funcs->get_virtual_call_data_func; + extension->gdextension.call_virtual_with_data = p_extension_funcs->call_virtual_with_data_func; extension->gdextension.get_rid = p_extension_funcs->get_rid_func; ClassDB::register_extension_class(&extension->gdextension); diff --git a/core/extension/gdextension_interface.h b/core/extension/gdextension_interface.h index 4214fce5f9..48cb28832a 100644 --- a/core/extension/gdextension_interface.h +++ b/core/extension/gdextension_interface.h @@ -265,9 +265,11 @@ typedef void (*GDExtensionClassToString)(GDExtensionClassInstancePtr p_instance, typedef void (*GDExtensionClassReference)(GDExtensionClassInstancePtr p_instance); typedef void (*GDExtensionClassUnreference)(GDExtensionClassInstancePtr p_instance); typedef void (*GDExtensionClassCallVirtual)(GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret); -typedef GDExtensionObjectPtr (*GDExtensionClassCreateInstance)(void *p_userdata); -typedef void (*GDExtensionClassFreeInstance)(void *p_userdata, GDExtensionClassInstancePtr p_instance); -typedef GDExtensionClassCallVirtual (*GDExtensionClassGetVirtual)(void *p_userdata, GDExtensionConstStringNamePtr p_name); +typedef GDExtensionObjectPtr (*GDExtensionClassCreateInstance)(void *p_class_userdata); +typedef void (*GDExtensionClassFreeInstance)(void *p_class_userdata, GDExtensionClassInstancePtr p_instance); +typedef GDExtensionClassCallVirtual (*GDExtensionClassGetVirtual)(void *p_class_userdata, GDExtensionConstStringNamePtr p_name); +typedef void *(*GDExtensionClassGetVirtualCallData)(void *p_class_userdata, GDExtensionConstStringNamePtr p_name); +typedef void (*GDExtensionClassCallVirtualWithData)(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, void *p_virtual_call_userdata, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_ret); typedef struct { GDExtensionBool is_virtual; @@ -306,7 +308,17 @@ typedef struct { GDExtensionClassUnreference unreference_func; GDExtensionClassCreateInstance create_instance_func; // (Default) constructor; mandatory. If the class is not instantiable, consider making it virtual or abstract. GDExtensionClassFreeInstance free_instance_func; // Destructor; mandatory. - GDExtensionClassGetVirtual get_virtual_func; // Queries a virtual function by name and returns a callback to invoke the requested virtual function. + // Queries a virtual function by name and returns a callback to invoke the requested virtual function. + GDExtensionClassGetVirtual get_virtual_func; + // Paired with `call_virtual_with_data_func`, this is an alternative to `get_virtual_func` for extensions that + // need or benefit from extra data when calling virtual functions. + // Returns user data that will be passed to `call_virtual_with_data_func`. + // Returning `NULL` from this function signals to Godot that the virtual function is not overridden. + // Data returned from this function should be managed by the extension and must be valid until the extension is deinitialized. + // You should supply either `get_virtual_func`, or `get_virtual_call_data_func` with `call_virtual_with_data_func`. + GDExtensionClassGetVirtualCallData get_virtual_call_data_func; + // Used to call virtual functions when `get_virtual_call_data_func` is not null. + GDExtensionClassCallVirtualWithData call_virtual_with_data_func; GDExtensionClassGetRID get_rid_func; void *class_userdata; // Per-class user data, later accessible in instance bindings. } GDExtensionClassCreationInfo2; diff --git a/core/object/make_virtuals.py b/core/object/make_virtuals.py index 38682d6d92..c2e69dc8e2 100644 --- a/core/object/make_virtuals.py +++ b/core/object/make_virtuals.py @@ -2,7 +2,7 @@ proto = """ #define GDVIRTUAL$VER($RET m_name $ARG) \\ StringName _gdvirtual_##m_name##_sn = #m_name;\\ mutable bool _gdvirtual_##m_name##_initialized = false;\\ -mutable GDExtensionClassCallVirtual _gdvirtual_##m_name = nullptr;\\ +mutable void* _gdvirtual_##m_name = nullptr;\\ template<bool required>\\ _FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\ ScriptInstance *_script_instance = ((Object*)(this))->get_script_instance();\\ @@ -16,15 +16,24 @@ _FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\ } \\ }\\ if (unlikely(_get_extension() && !_gdvirtual_##m_name##_initialized)) {\\ - /* TODO: C-style cast because GDExtensionStringNamePtr's const qualifier is broken (see https://github.com/godotengine/godot/pull/67751) */\\ - _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, (GDExtensionStringNamePtr)&_gdvirtual_##m_name##_sn) : (GDExtensionClassCallVirtual) nullptr;\\ + _gdvirtual_##m_name = nullptr;\\ + if (_get_extension()->get_virtual_call_data && _get_extension()->call_virtual_with_data) {\\ + _gdvirtual_##m_name = _get_extension()->get_virtual_call_data(_get_extension()->class_userdata, &_gdvirtual_##m_name##_sn);\\ + } else if (_get_extension()->get_virtual) {\\ + _gdvirtual_##m_name = (void *)_get_extension()->get_virtual(_get_extension()->class_userdata, &_gdvirtual_##m_name##_sn);\\ + }\\ _gdvirtual_##m_name##_initialized = true;\\ }\\ if (_gdvirtual_##m_name) {\\ $CALLPTRARGS\\ $CALLPTRRETDEF\\ - _gdvirtual_##m_name(_get_extension_instance(),$CALLPTRARGPASS,$CALLPTRRETPASS);\\ - $CALLPTRRET\\ + if (_get_extension()->get_virtual_call_data && _get_extension()->call_virtual_with_data) {\\ + _get_extension()->call_virtual_with_data(_get_extension_instance(), &_gdvirtual_##m_name##_sn, _gdvirtual_##m_name, $CALLPTRARGPASS,$CALLPTRRETPASS);\\ + $CALLPTRRET\\ + } else {\\ + ((GDExtensionClassCallVirtual)_gdvirtual_##m_name)(_get_extension_instance(),$CALLPTRARGPASS,$CALLPTRRETPASS);\\ + $CALLPTRRET\\ + }\\ return true;\\ }\\ \\ @@ -41,8 +50,12 @@ _FORCE_INLINE_ bool _gdvirtual_##m_name##_overridden() const { \\ return _script_instance->has_method(_gdvirtual_##m_name##_sn);\\ }\\ if (unlikely(_get_extension() && !_gdvirtual_##m_name##_initialized)) {\\ - /* TODO: C-style cast because GDExtensionStringNamePtr's const qualifier is broken (see https://github.com/godotengine/godot/pull/67751) */\\ - _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, (GDExtensionStringNamePtr)&_gdvirtual_##m_name##_sn) : (GDExtensionClassCallVirtual) nullptr;\\ + _gdvirtual_##m_name = nullptr;\\ + if (_get_extension()->get_virtual_call_data && _get_extension()->call_virtual_with_data) {\\ + _gdvirtual_##m_name = _get_extension()->get_virtual_call_data(_get_extension()->class_userdata, &_gdvirtual_##m_name##_sn);\\ + } else if (_get_extension()->get_virtual) {\\ + _gdvirtual_##m_name = (void *)_get_extension()->get_virtual(_get_extension()->class_userdata, &_gdvirtual_##m_name##_sn);\\ + }\\ _gdvirtual_##m_name##_initialized = true;\\ }\\ if (_gdvirtual_##m_name) {\\ diff --git a/core/object/object.h b/core/object/object.h index 3a698f7526..7da1c68edf 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -347,6 +347,8 @@ struct ObjectGDExtension { GDExtensionClassCreateInstance create_instance; GDExtensionClassFreeInstance free_instance; GDExtensionClassGetVirtual get_virtual; + GDExtensionClassGetVirtualCallData get_virtual_call_data; + GDExtensionClassCallVirtualWithData call_virtual_with_data; }; #define GDVIRTUAL_CALL(m_name, ...) _gdvirtual_##m_name##_call<false>(__VA_ARGS__) diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 87c642c6d3..fe5269e95d 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -2117,11 +2117,11 @@ [codeblocks] [gdscript] # Set the default gravity strength to 9.8. - PhysicsServer3D.area_set_param(get_viewport().find_world().space, PhysicsServer3D.AREA_PARAM_GRAVITY, 9.8) + PhysicsServer3D.area_set_param(get_viewport().find_world_3d().space, PhysicsServer3D.AREA_PARAM_GRAVITY, 9.8) [/gdscript] [csharp] // Set the default gravity strength to 9.8. - PhysicsServer3D.AreaSetParam(GetViewport().FindWorld().Space, PhysicsServer3D.AreaParameter.Gravity, 9.8); + PhysicsServer3D.AreaSetParam(GetViewport().FindWorld3D().Space, PhysicsServer3D.AreaParameter.Gravity, 9.8); [/csharp] [/codeblocks] </member> @@ -2131,11 +2131,11 @@ [codeblocks] [gdscript] # Set the default gravity direction to `Vector3(0, -1, 0)`. - PhysicsServer3D.area_set_param(get_viewport().find_world().get_space(), PhysicsServer3D.AREA_PARAM_GRAVITY_VECTOR, Vector3.DOWN) + PhysicsServer3D.area_set_param(get_viewport().find_world_3d().space, PhysicsServer3D.AREA_PARAM_GRAVITY_VECTOR, Vector3.DOWN) [/gdscript] [csharp] // Set the default gravity direction to `Vector3(0, -1, 0)`. - PhysicsServer3D.AreaSetParam(GetViewport().FindWorld().Space, PhysicsServer3D.AreaParameter.GravityVector, Vector3.Down) + PhysicsServer3D.AreaSetParam(GetViewport().FindWorld3D().Space, PhysicsServer3D.AreaParameter.GravityVector, Vector3.Down) [/csharp] [/codeblocks] </member> diff --git a/editor/icons/TorusMesh.svg b/editor/icons/TorusMesh.svg index c720b59aa5..adf3a8403b 100644 --- a/editor/icons/TorusMesh.svg +++ b/editor/icons/TorusMesh.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><ellipse cx="8" cy="7.5" fill="none" rx="6" ry="3.5" stroke="#ffca5f" stroke-width="2"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#ffca5f"><path d="M2.5 10a6 4 0 0 0 11 0 4 4 0 0 0 0-4 6 4 0 0 0-11 0 4 4 0 0 0 0 4z" stroke-width="2"/><path d="M6.2 7.2a2 1 0 1 0 3.6 0" stroke-width="1.75" stroke-linecap="round"/></g></svg> diff --git a/modules/csg/icons/CSGTorus3D.svg b/modules/csg/icons/CSGTorus3D.svg index 5672244e5c..27a6b422f9 100644 --- a/modules/csg/icons/CSGTorus3D.svg +++ b/modules/csg/icons/CSGTorus3D.svg @@ -1 +1 @@ -<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><mask id="a"><path d="M0 0h16v10a2 2 0 0 0-2-2h-2a2 2 0 0 0-2 2 2 2 0 0 0-2 2v2a2 2 0 0 0 2 2H0z" fill="#fff"/></mask><path d="M12 9a1 1 0 0 0-1 1v1h2v2h1a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1zm1 4h-2v-2h-1a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1z" fill="#5fb2ff"/><ellipse cx="8" cy="7.5" fill="none" rx="6" ry="3.5" stroke="#fc7f7f" stroke-width="2" mask="url(#a)"/></svg> +<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><mask id="a"><path d="M0 0h16v10a2 2 0 0 0-2-2h-2a2 2 0 0 0-2 2 2 2 0 0 0-2 2v2a2 2 0 0 0 2 2H0z" fill="#fff"/></mask><path d="M12 9a1 1 0 0 0-1 1v1h2v2h1a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1zm1 4h-2v-2h-1a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1z" fill="#5fb2ff"/><g fill="none" stroke="#fc7f7f" mask="url(#a)"><path d="M2.5 10a6 4 0 0 0 11 0 4 4 0 0 0 0-4 6 4 0 0 0-11 0 4 4 0 0 0 0 4z" stroke-width="2"/><path d="M6.2 7.2a2 1 0 1 0 3.6 0" stroke-width="1.75" stroke-linecap="round"/></g></svg> diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index b41f2155f8..26c684f769 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -2353,6 +2353,8 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) { mi.arguments.push_back(arg_info); } + mi.flags = (uint32_t)method_info_dict["flags"]; + p_script->methods.set(push_index++, CSharpMethodInfo{ name, mi }); } @@ -2602,6 +2604,18 @@ MethodInfo CSharpScript::get_method_info(const StringName &p_method) const { return MethodInfo(); } +Variant CSharpScript::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) { + ERR_FAIL_COND_V(!valid, Variant()); + + Variant ret; + bool ok = GDMonoCache::managed_callbacks.ScriptManagerBridge_CallStatic(this, &p_method, p_args, p_argcount, &r_error, &ret); + if (ok) { + return ret; + } + + return Script::callp(p_method, p_args, p_argcount, r_error); +} + Error CSharpScript::reload(bool p_keep_state) { if (!reload_invalidated) { return OK; diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index 33862016a4..fd9e281e63 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -199,6 +199,7 @@ public: void get_script_method_list(List<MethodInfo> *p_list) const override; bool has_method(const StringName &p_method) const override; MethodInfo get_method_info(const StringName &p_method) const override; + Variant callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override; int get_member_line(const StringName &p_member) const override; diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs index 5ea0ca53c3..7b643914bb 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs @@ -125,7 +125,7 @@ namespace Godot.SourceGenerators var members = symbol.GetMembers(); var methodSymbols = members - .Where(s => !s.IsStatic && s.Kind == SymbolKind.Method && !s.IsImplicitlyDeclared) + .Where(s => s.Kind == SymbolKind.Method && !s.IsImplicitlyDeclared) .Cast<IMethodSymbol>() .Where(m => m.MethodKind == MethodKind.Ordinary); @@ -221,6 +221,29 @@ namespace Godot.SourceGenerators source.Append(" }\n"); } + // Generate InvokeGodotClassStaticMethod + + var godotClassStaticMethods = godotClassMethods.Where(m => m.Method.IsStatic).ToArray(); + + if (godotClassStaticMethods.Length > 0) + { + source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n"); + source.Append(" [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]\n"); + source.Append(" internal new static bool InvokeGodotClassStaticMethod(in godot_string_name method, "); + source.Append("NativeVariantPtrArgs args, out godot_variant ret)\n {\n"); + + foreach (var method in godotClassStaticMethods) + { + GenerateMethodInvoker(method, source); + } + + source.Append(" ret = default;\n"); + source.Append(" return false;\n"); + source.Append(" }\n"); + + source.Append("#pragma warning restore CS0109\n"); + } + // Generate HasGodotClassMethod if (distinctMethodNames.Length > 0) @@ -356,7 +379,14 @@ namespace Godot.SourceGenerators arguments = null; } - return new MethodInfo(method.Method.Name, returnVal, MethodFlags.Default, arguments, + MethodFlags flags = MethodFlags.Default; + + if (method.Method.IsStatic) + { + flags |= MethodFlags.Static; + } + + return new MethodInfo(method.Method.Name, returnVal, flags, arguments, defaultArguments: null); } diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs index 1c1185d91b..e186c0302b 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs +++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs @@ -190,6 +190,9 @@ namespace GodotTools case ExternalEditorId.CustomEditor: { string file = ProjectSettings.GlobalizePath(script.ResourcePath); + string project = ProjectSettings.GlobalizePath("res://"); + // Since ProjectSettings.GlobalizePath replaces only "res:/", leaving a trailing slash, it is removed here. + project = project[..^1]; var execCommand = _editorSettings.GetSetting(Settings.CustomExecPath).As<string>(); var execArgs = _editorSettings.GetSetting(Settings.CustomExecPathArgs).As<string>(); var args = new List<string>(); @@ -226,6 +229,7 @@ namespace GodotTools hasFileFlag = true; } + arg = arg.ReplaceN("{project}", project); arg = arg.ReplaceN("{file}", file); args.Add(arg); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ManagedCallbacks.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ManagedCallbacks.cs index 109643c2d4..5d6583b404 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ManagedCallbacks.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ManagedCallbacks.cs @@ -29,6 +29,7 @@ namespace Godot.Bridge public delegate* unmanaged<IntPtr, IntPtr*, godot_bool, godot_bool> ScriptManagerBridge_SwapGCHandleForType; public delegate* unmanaged<IntPtr, delegate* unmanaged<IntPtr, godot_string*, void*, int, void>, void> ScriptManagerBridge_GetPropertyInfoList; public delegate* unmanaged<IntPtr, delegate* unmanaged<IntPtr, void*, int, void>, void> ScriptManagerBridge_GetPropertyDefaultValues; + public delegate* unmanaged<IntPtr, godot_string_name*, godot_variant**, int, godot_variant_call_error*, godot_variant*, godot_bool> ScriptManagerBridge_CallStatic; public delegate* unmanaged<IntPtr, godot_string_name*, godot_variant**, int, godot_variant_call_error*, godot_variant*, godot_bool> CSharpInstanceBridge_Call; public delegate* unmanaged<IntPtr, godot_string_name*, godot_variant*, godot_bool> CSharpInstanceBridge_Set; public delegate* unmanaged<IntPtr, godot_string_name*, godot_variant*, godot_bool> CSharpInstanceBridge_Get; @@ -70,6 +71,7 @@ namespace Godot.Bridge ScriptManagerBridge_SwapGCHandleForType = &ScriptManagerBridge.SwapGCHandleForType, ScriptManagerBridge_GetPropertyInfoList = &ScriptManagerBridge.GetPropertyInfoList, ScriptManagerBridge_GetPropertyDefaultValues = &ScriptManagerBridge.GetPropertyDefaultValues, + ScriptManagerBridge_CallStatic = &ScriptManagerBridge.CallStatic, CSharpInstanceBridge_Call = &CSharpInstanceBridge.Call, CSharpInstanceBridge_Set = &CSharpInstanceBridge.Set, CSharpInstanceBridge_Get = &CSharpInstanceBridge.Get, diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs index 0fe4bcdfce..1a7d2d9075 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs @@ -90,7 +90,7 @@ namespace Godot.Bridge internal static unsafe IntPtr CreateManagedForGodotObjectBinding(godot_string_name* nativeTypeName, IntPtr godotObject) { - // TODO: Optimize with source generators and delegate pointers + // TODO: Optimize with source generators and delegate pointers. try { @@ -124,7 +124,7 @@ namespace Godot.Bridge IntPtr godotObject, godot_variant** args, int argCount) { - // TODO: Optimize with source generators and delegate pointers + // TODO: Optimize with source generators and delegate pointers. try { @@ -677,6 +677,8 @@ namespace Godot.Bridge methodInfo.Add("params", methodParams); + methodInfo.Add("flags", (int)method.Flags); + methods.Add(methodInfo); } } @@ -958,6 +960,54 @@ namespace Godot.Bridge public godot_variant Value; // Not owned } + private delegate bool InvokeGodotClassStaticMethodDelegate(in godot_string_name method, NativeVariantPtrArgs args, out godot_variant ret); + + [UnmanagedCallersOnly] + internal static unsafe godot_bool CallStatic(IntPtr scriptPtr, godot_string_name* method, + godot_variant** args, int argCount, godot_variant_call_error* refCallError, godot_variant* ret) + { + // TODO: Optimize with source generators and delegate pointers. + + try + { + Type scriptType = _scriptTypeBiMap.GetScriptType(scriptPtr); + + Type? top = scriptType; + Type native = GodotObject.InternalGetClassNativeBase(top); + + while (top != null && top != native) + { + var invokeGodotClassStaticMethod = top.GetMethod( + "InvokeGodotClassStaticMethod", + BindingFlags.DeclaredOnly | BindingFlags.Static | + BindingFlags.NonPublic | BindingFlags.Public); + + if (invokeGodotClassStaticMethod != null) + { + var invoked = invokeGodotClassStaticMethod.CreateDelegate<InvokeGodotClassStaticMethodDelegate>()( + CustomUnsafe.AsRef(method), new NativeVariantPtrArgs(args, argCount), out godot_variant retValue); + if (invoked) + { + *ret = retValue; + return godot_bool.True; + } + } + + top = top.BaseType; + } + } + catch (Exception e) + { + ExceptionUtils.LogException(e); + *ret = default; + return godot_bool.False; + } + + *ret = default; + (*refCallError).Error = godot_variant_call_error_error.GODOT_CALL_ERROR_CALL_ERROR_INVALID_METHOD; + return godot_bool.False; + } + [UnmanagedCallersOnly] internal static unsafe void GetPropertyDefaultValues(IntPtr scriptPtr, delegate* unmanaged<IntPtr, void*, int, void> addDefValFunc) diff --git a/modules/mono/mono_gd/gd_mono_cache.cpp b/modules/mono/mono_gd/gd_mono_cache.cpp index 8fdf163b26..5a1f90fa1d 100644 --- a/modules/mono/mono_gd/gd_mono_cache.cpp +++ b/modules/mono/mono_gd/gd_mono_cache.cpp @@ -70,6 +70,7 @@ void update_godot_api_cache(const ManagedCallbacks &p_managed_callbacks) { CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, SwapGCHandleForType); CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, GetPropertyInfoList); CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, GetPropertyDefaultValues); + CHECK_CALLBACK_NOT_NULL(ScriptManagerBridge, CallStatic); CHECK_CALLBACK_NOT_NULL(CSharpInstanceBridge, Call); CHECK_CALLBACK_NOT_NULL(CSharpInstanceBridge, Set); CHECK_CALLBACK_NOT_NULL(CSharpInstanceBridge, Get); diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h index f604e4d681..6ddc688ea0 100644 --- a/modules/mono/mono_gd/gd_mono_cache.h +++ b/modules/mono/mono_gd/gd_mono_cache.h @@ -95,6 +95,7 @@ struct ManagedCallbacks { using FuncScriptManagerBridge_SwapGCHandleForType = bool(GD_CLR_STDCALL *)(GCHandleIntPtr, GCHandleIntPtr *, bool); using FuncScriptManagerBridge_GetPropertyInfoList = void(GD_CLR_STDCALL *)(CSharpScript *, Callback_ScriptManagerBridge_GetPropertyInfoList_Add); using FuncScriptManagerBridge_GetPropertyDefaultValues = void(GD_CLR_STDCALL *)(CSharpScript *, Callback_ScriptManagerBridge_GetPropertyDefaultValues_Add); + using FuncScriptManagerBridge_CallStatic = bool(GD_CLR_STDCALL *)(const CSharpScript *, const StringName *, const Variant **, int32_t, Callable::CallError *, Variant *); using FuncCSharpInstanceBridge_Call = bool(GD_CLR_STDCALL *)(GCHandleIntPtr, const StringName *, const Variant **, int32_t, Callable::CallError *, Variant *); using FuncCSharpInstanceBridge_Set = bool(GD_CLR_STDCALL *)(GCHandleIntPtr, const StringName *, const Variant *); using FuncCSharpInstanceBridge_Get = bool(GD_CLR_STDCALL *)(GCHandleIntPtr, const StringName *, Variant *); @@ -130,6 +131,7 @@ struct ManagedCallbacks { FuncScriptManagerBridge_SwapGCHandleForType ScriptManagerBridge_SwapGCHandleForType; FuncScriptManagerBridge_GetPropertyInfoList ScriptManagerBridge_GetPropertyInfoList; FuncScriptManagerBridge_GetPropertyDefaultValues ScriptManagerBridge_GetPropertyDefaultValues; + FuncScriptManagerBridge_CallStatic ScriptManagerBridge_CallStatic; FuncCSharpInstanceBridge_Call CSharpInstanceBridge_Call; FuncCSharpInstanceBridge_Set CSharpInstanceBridge_Set; FuncCSharpInstanceBridge_Get CSharpInstanceBridge_Get; diff --git a/platform/macos/detect.py b/platform/macos/detect.py index 21e824b2d3..6abe121407 100644 --- a/platform/macos/detect.py +++ b/platform/macos/detect.py @@ -1,6 +1,6 @@ import os import sys -from methods import detect_darwin_sdk_path +from methods import detect_darwin_sdk_path, get_compiler_version, is_vanilla_clang from platform_methods import detect_arch from typing import TYPE_CHECKING @@ -119,6 +119,22 @@ def configure(env: "Environment"): env.Append(CCFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.13"]) env.Append(LINKFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.13"]) + cc_version = get_compiler_version(env) or { + "major": None, + "minor": None, + "patch": None, + "metadata1": None, + "metadata2": None, + "date": None, + } + cc_version_major = int(cc_version["major"] or -1) + cc_version_minor = int(cc_version["minor"] or -1) + vanilla = is_vanilla_clang(env) + + # Workaround for Xcode 15 linker bug. + if not vanilla and cc_version_major == 15 and cc_version_minor == 0: + env.Prepend(LINKFLAGS=["-ld_classic"]) + env.Append(CCFLAGS=["-fobjc-arc"]) if not "osxcross" in env: # regular native build diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl index cfba408fe1..2b8b8fa9d2 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl @@ -1277,9 +1277,10 @@ void fragment_shader(in SceneData scene_data) { } else if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap bool uses_sh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP); uint ofs = instances.data[instance_index].gi_offset & 0xFFFF; + uint slice = instances.data[instance_index].gi_offset >> 16; vec3 uvw; uvw.xy = uv2 * instances.data[instance_index].lightmap_uv_scale.zw + instances.data[instance_index].lightmap_uv_scale.xy; - uvw.z = float((instances.data[instance_index].gi_offset >> 16) & 0xFFFF); + uvw.z = float(slice); if (uses_sh) { uvw.z *= 4.0; //SH textures use 4 times more data @@ -1288,9 +1289,8 @@ void fragment_shader(in SceneData scene_data) { vec3 lm_light_l1_0 = textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw + vec3(0.0, 0.0, 2.0), 0.0).rgb; vec3 lm_light_l1p1 = textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw + vec3(0.0, 0.0, 3.0), 0.0).rgb; - uint idx = instances.data[instance_index].gi_offset >> 20; - vec3 n = normalize(lightmaps.data[idx].normal_xform * normal); - float en = lightmaps.data[idx].exposure_normalization; + vec3 n = normalize(lightmaps.data[ofs].normal_xform * normal); + float en = lightmaps.data[ofs].exposure_normalization; ambient_light += lm_light_l0 * 0.282095f * en; ambient_light += lm_light_l1n1 * 0.32573 * n.y * en; @@ -1304,8 +1304,7 @@ void fragment_shader(in SceneData scene_data) { } } else { - uint idx = instances.data[instance_index].gi_offset >> 20; - ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw, 0.0).rgb * lightmaps.data[idx].exposure_normalization; + ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw, 0.0).rgb * lightmaps.data[ofs].exposure_normalization; } } #else diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl index cdf81bb6ec..7f6a9a50e5 100644 --- a/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl @@ -1121,11 +1121,10 @@ void main() { } else if (bool(draw_call.flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap bool uses_sh = bool(draw_call.flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP); uint ofs = draw_call.gi_offset & 0xFFFF; + uint slice = draw_call.gi_offset >> 16; vec3 uvw; uvw.xy = uv2 * draw_call.lightmap_uv_scale.zw + draw_call.lightmap_uv_scale.xy; - uvw.z = float((draw_call.gi_offset >> 16) & 0xFFFF); - - uint idx = draw_call.gi_offset >> 20; + uvw.z = float(slice); if (uses_sh) { uvw.z *= 4.0; //SH textures use 4 times more data @@ -1134,8 +1133,8 @@ void main() { vec3 lm_light_l1_0 = textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw + vec3(0.0, 0.0, 2.0), 0.0).rgb; vec3 lm_light_l1p1 = textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw + vec3(0.0, 0.0, 3.0), 0.0).rgb; - vec3 n = normalize(lightmaps.data[idx].normal_xform * normal); - float exposure_normalization = lightmaps.data[idx].exposure_normalization; + vec3 n = normalize(lightmaps.data[ofs].normal_xform * normal); + float exposure_normalization = lightmaps.data[ofs].exposure_normalization; ambient_light += lm_light_l0 * 0.282095f; ambient_light += lm_light_l1n1 * 0.32573 * n.y * exposure_normalization; @@ -1149,7 +1148,7 @@ void main() { } } else { - ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw, 0.0).rgb * lightmaps.data[idx].exposure_normalization; + ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw, 0.0).rgb * lightmaps.data[ofs].exposure_normalization; } } |