feat: updated engine version to 4.4-rc1
This commit is contained in:
parent
ee00efde1f
commit
21ba8e33af
5459 changed files with 1128836 additions and 198305 deletions
|
|
@ -2,21 +2,14 @@
|
|||
end_of_line = crlf
|
||||
charset = utf-8-bom
|
||||
|
||||
[*.sln]
|
||||
indent_style = tab
|
||||
|
||||
[*.{csproj,props,targets,nuspec,resx}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.cs]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
max_line_length = 120
|
||||
csharp_indent_case_contents_when_block = false
|
||||
|
||||
csharp_indent_case_contents_when_block = false
|
||||
csharp_new_line_before_open_brace = all
|
||||
csharp_new_line_before_else = true
|
||||
csharp_new_line_before_catch = true
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
import build_scripts.mono_configure as mono_configure
|
||||
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ def run_msbuild(tools: ToolsLocation, sln: str, chdir_to: str, msbuild_args: Opt
|
|||
return subprocess.call(args, env=msbuild_env, cwd=chdir_to)
|
||||
|
||||
|
||||
def build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local, precision):
|
||||
def build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local, precision, no_deprecated, werror):
|
||||
target_filenames = [
|
||||
"GodotSharp.dll",
|
||||
"GodotSharp.pdb",
|
||||
|
|
@ -217,6 +217,10 @@ def build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local, pre
|
|||
args += ["/p:ClearNuGetLocalCache=true", "/p:PushNuGetToLocalSource=" + push_nupkgs_local]
|
||||
if precision == "double":
|
||||
args += ["/p:GodotFloat64=true"]
|
||||
if no_deprecated:
|
||||
args += ["/p:GodotNoDeprecated=true"]
|
||||
if werror:
|
||||
args += ["/p:TreatWarningsAsErrors=true"]
|
||||
|
||||
sln = os.path.join(module_dir, "glue/GodotSharp/GodotSharp.sln")
|
||||
exit_code = run_msbuild(msbuild_tool, sln=sln, chdir_to=module_dir, msbuild_args=args)
|
||||
|
|
@ -227,7 +231,7 @@ def build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local, pre
|
|||
|
||||
core_src_dir = os.path.abspath(os.path.join(sln, os.pardir, "GodotSharp", "bin", build_config))
|
||||
editor_src_dir = os.path.abspath(os.path.join(sln, os.pardir, "GodotSharpEditor", "bin", build_config))
|
||||
plugins_src_dir = os.path.abspath(os.path.join(sln, os.pardir, "GodotPlugins", "bin", build_config, "net6.0"))
|
||||
plugins_src_dir = os.path.abspath(os.path.join(sln, os.pardir, "GodotPlugins", "bin", build_config, "net8.0"))
|
||||
|
||||
if not os.path.isdir(editor_api_dir):
|
||||
assert not os.path.isfile(editor_api_dir)
|
||||
|
|
@ -336,12 +340,16 @@ def generate_sdk_package_versions():
|
|||
f.write(constants)
|
||||
|
||||
|
||||
def build_all(msbuild_tool, module_dir, output_dir, godot_platform, dev_debug, push_nupkgs_local, precision):
|
||||
def build_all(
|
||||
msbuild_tool, module_dir, output_dir, godot_platform, dev_debug, push_nupkgs_local, precision, no_deprecated, werror
|
||||
):
|
||||
# Generate SdkPackageVersions.props and VersionDocsUrl constant
|
||||
generate_sdk_package_versions()
|
||||
|
||||
# Godot API
|
||||
exit_code = build_godot_api(msbuild_tool, module_dir, output_dir, push_nupkgs_local, precision)
|
||||
exit_code = build_godot_api(
|
||||
msbuild_tool, module_dir, output_dir, push_nupkgs_local, precision, no_deprecated, werror
|
||||
)
|
||||
if exit_code != 0:
|
||||
return exit_code
|
||||
|
||||
|
|
@ -364,6 +372,8 @@ def build_all(msbuild_tool, module_dir, output_dir, godot_platform, dev_debug, p
|
|||
args += ["/p:ClearNuGetLocalCache=true", "/p:PushNuGetToLocalSource=" + push_nupkgs_local]
|
||||
if precision == "double":
|
||||
args += ["/p:GodotFloat64=true"]
|
||||
if no_deprecated:
|
||||
args += ["/p:GodotNoDeprecated=true"]
|
||||
sln = os.path.join(module_dir, "editor/Godot.NET.Sdk/Godot.NET.Sdk.sln")
|
||||
exit_code = run_msbuild(msbuild_tool, sln=sln, chdir_to=module_dir, msbuild_args=args)
|
||||
if exit_code != 0:
|
||||
|
|
@ -390,6 +400,13 @@ def main():
|
|||
parser.add_argument(
|
||||
"--precision", type=str, default="single", choices=["single", "double"], help="Floating-point precision level"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-deprecated",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Build GodotSharp without using deprecated features. This is required, if the engine was built with 'deprecated=no'.",
|
||||
)
|
||||
parser.add_argument("--werror", action="store_true", default=False, help="Treat compiler warnings as errors.")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
|
|
@ -414,6 +431,8 @@ def main():
|
|||
args.dev_debug,
|
||||
push_nupkgs_local,
|
||||
args.precision,
|
||||
args.no_deprecated,
|
||||
args.werror,
|
||||
)
|
||||
sys.exit(exit_code)
|
||||
|
||||
|
|
|
|||
|
|
@ -11,9 +11,11 @@ def can_build(env, platform):
|
|||
def configure(env):
|
||||
# Check if the platform has marked mono as supported.
|
||||
supported = env.get("supported", [])
|
||||
|
||||
if "mono" not in supported:
|
||||
raise RuntimeError("This module does not currently support building for this platform")
|
||||
import sys
|
||||
|
||||
print("The 'mono' module does not currently support building for this platform. Aborting.")
|
||||
sys.exit(255)
|
||||
|
||||
env.add_module_version_string("mono")
|
||||
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ void CSharpLanguage::finalize() {
|
|||
|
||||
finalizing = true;
|
||||
|
||||
// Make sure all script binding gchandles are released before finalizing GDMono
|
||||
// Make sure all script binding gchandles are released before finalizing GDMono.
|
||||
for (KeyValue<Object *, CSharpScriptBinding> &E : script_bindings) {
|
||||
CSharpScriptBinding &script_binding = E.value;
|
||||
|
||||
|
|
@ -156,6 +156,10 @@ void CSharpLanguage::finalize() {
|
|||
script_binding.gchandle.release();
|
||||
script_binding.inited = false;
|
||||
}
|
||||
|
||||
// Make sure we clear all the instance binding callbacks so they don't get called
|
||||
// after finalizing the C# language.
|
||||
script_binding.owner->free_instance_binding(this);
|
||||
}
|
||||
|
||||
if (gdmono) {
|
||||
|
|
@ -441,9 +445,9 @@ bool CSharpLanguage::handles_global_class_type(const String &p_type) const {
|
|||
return p_type == get_type();
|
||||
}
|
||||
|
||||
String CSharpLanguage::get_global_class_name(const String &p_path, String *r_base_type, String *r_icon_path) const {
|
||||
String CSharpLanguage::get_global_class_name(const String &p_path, String *r_base_type, String *r_icon_path, bool *r_is_abstract, bool *r_is_tool) const {
|
||||
String class_name;
|
||||
GDMonoCache::managed_callbacks.ScriptManagerBridge_GetGlobalClassName(&p_path, r_base_type, r_icon_path, &class_name);
|
||||
GDMonoCache::managed_callbacks.ScriptManagerBridge_GetGlobalClassName(&p_path, r_base_type, r_icon_path, r_is_abstract, r_is_tool, &class_name);
|
||||
return class_name;
|
||||
}
|
||||
|
||||
|
|
@ -496,8 +500,8 @@ Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info()
|
|||
}
|
||||
_recursion_flag_ = true;
|
||||
SCOPE_EXIT {
|
||||
_recursion_flag_ = false;
|
||||
};
|
||||
_recursion_flag_ = false; // clang-format off
|
||||
}; // clang-format on
|
||||
|
||||
if (!gdmono || !gdmono->is_runtime_initialized()) {
|
||||
return Vector<StackInfo>();
|
||||
|
|
@ -1227,6 +1231,11 @@ void CSharpLanguage::_instance_binding_free_callback(void *, void *, void *p_bin
|
|||
}
|
||||
|
||||
GDExtensionBool CSharpLanguage::_instance_binding_reference_callback(void *p_token, void *p_binding, GDExtensionBool p_reference) {
|
||||
// Instance bindings callbacks can only be called if the C# language is available.
|
||||
// Failing this assert usually means that we didn't clear the instance binding in some Object
|
||||
// and the C# language has already been finalized.
|
||||
DEV_ASSERT(CSharpLanguage::get_singleton() != nullptr);
|
||||
|
||||
CRASH_COND(!p_binding);
|
||||
|
||||
CSharpScriptBinding &script_binding = ((RBMap<Object *, CSharpScriptBinding>::Element *)p_binding)->get();
|
||||
|
|
@ -1464,14 +1473,14 @@ Object *CSharpInstance::get_owner() {
|
|||
}
|
||||
|
||||
bool CSharpInstance::set(const StringName &p_name, const Variant &p_value) {
|
||||
ERR_FAIL_COND_V(!script.is_valid(), false);
|
||||
ERR_FAIL_COND_V(script.is_null(), false);
|
||||
|
||||
return GDMonoCache::managed_callbacks.CSharpInstanceBridge_Set(
|
||||
gchandle.get_intptr(), &p_name, &p_value);
|
||||
}
|
||||
|
||||
bool CSharpInstance::get(const StringName &p_name, Variant &r_ret) const {
|
||||
ERR_FAIL_COND_V(!script.is_valid(), false);
|
||||
ERR_FAIL_COND_V(script.is_null(), false);
|
||||
|
||||
Variant ret_value;
|
||||
|
||||
|
|
@ -1488,12 +1497,24 @@ bool CSharpInstance::get(const StringName &p_name, Variant &r_ret) const {
|
|||
|
||||
void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const {
|
||||
List<PropertyInfo> props;
|
||||
script->get_script_property_list(&props);
|
||||
ERR_FAIL_COND(script.is_null());
|
||||
#ifdef TOOLS_ENABLED
|
||||
for (const PropertyInfo &prop : script->exported_members_cache) {
|
||||
props.push_back(prop);
|
||||
}
|
||||
#else
|
||||
for (const KeyValue<StringName, PropertyInfo> &E : script->member_info) {
|
||||
props.push_front(E.value);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (PropertyInfo &prop : props) {
|
||||
validate_property(prop);
|
||||
p_properties->push_back(prop);
|
||||
}
|
||||
|
||||
// Call _get_property_list
|
||||
|
||||
ERR_FAIL_COND(!script.is_valid());
|
||||
|
||||
StringName method = SNAME("_get_property_list");
|
||||
|
||||
Variant ret;
|
||||
|
|
@ -1515,9 +1536,25 @@ void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const {
|
|||
}
|
||||
}
|
||||
|
||||
for (PropertyInfo &prop : props) {
|
||||
validate_property(prop);
|
||||
p_properties->push_back(prop);
|
||||
CSharpScript *top = script.ptr()->base_script.ptr();
|
||||
while (top != nullptr) {
|
||||
props.clear();
|
||||
#ifdef TOOLS_ENABLED
|
||||
for (const PropertyInfo &prop : top->exported_members_cache) {
|
||||
props.push_back(prop);
|
||||
}
|
||||
#else
|
||||
for (const KeyValue<StringName, PropertyInfo> &E : top->member_info) {
|
||||
props.push_front(E.value);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (PropertyInfo &prop : props) {
|
||||
validate_property(prop);
|
||||
p_properties->push_back(prop);
|
||||
}
|
||||
|
||||
top = top->base_script.ptr();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1537,7 +1574,7 @@ Variant::Type CSharpInstance::get_property_type(const StringName &p_name, bool *
|
|||
}
|
||||
|
||||
bool CSharpInstance::property_can_revert(const StringName &p_name) const {
|
||||
ERR_FAIL_COND_V(!script.is_valid(), false);
|
||||
ERR_FAIL_COND_V(script.is_null(), false);
|
||||
|
||||
Variant name_arg = p_name;
|
||||
const Variant *args[1] = { &name_arg };
|
||||
|
|
@ -1555,7 +1592,7 @@ bool CSharpInstance::property_can_revert(const StringName &p_name) const {
|
|||
}
|
||||
|
||||
void CSharpInstance::validate_property(PropertyInfo &p_property) const {
|
||||
ERR_FAIL_COND(!script.is_valid());
|
||||
ERR_FAIL_COND(script.is_null());
|
||||
|
||||
Variant property_arg = (Dictionary)p_property;
|
||||
const Variant *args[1] = { &property_arg };
|
||||
|
|
@ -1573,7 +1610,7 @@ void CSharpInstance::validate_property(PropertyInfo &p_property) const {
|
|||
}
|
||||
|
||||
bool CSharpInstance::property_get_revert(const StringName &p_name, Variant &r_ret) const {
|
||||
ERR_FAIL_COND_V(!script.is_valid(), false);
|
||||
ERR_FAIL_COND_V(script.is_null(), false);
|
||||
|
||||
Variant name_arg = p_name;
|
||||
const Variant *args[1] = { &name_arg };
|
||||
|
|
@ -1600,7 +1637,7 @@ void CSharpInstance::get_method_list(List<MethodInfo> *p_list) const {
|
|||
}
|
||||
|
||||
bool CSharpInstance::has_method(const StringName &p_method) const {
|
||||
if (!script.is_valid()) {
|
||||
if (script.is_null()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1641,7 +1678,7 @@ int CSharpInstance::get_method_argument_count(const StringName &p_method, bool *
|
|||
}
|
||||
|
||||
Variant CSharpInstance::callp(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
|
||||
ERR_FAIL_COND_V(!script.is_valid(), Variant());
|
||||
ERR_FAIL_COND_V(script.is_null(), Variant());
|
||||
|
||||
Variant ret;
|
||||
GDMonoCache::managed_callbacks.CSharpInstanceBridge_Call(
|
||||
|
|
@ -1662,7 +1699,7 @@ bool CSharpInstance::_reference_owner_unsafe() {
|
|||
// but the managed instance is alive, the refcount will be 1 instead of 0.
|
||||
// See: _unreference_owner_unsafe()
|
||||
|
||||
// May not me referenced yet, so we must use init_ref() instead of reference()
|
||||
// May not be referenced yet, so we must use init_ref() instead of reference()
|
||||
if (static_cast<RefCounted *>(owner)->init_ref()) {
|
||||
CSharpLanguage::get_singleton()->post_unsafe_reference(owner);
|
||||
unsafe_referenced = true;
|
||||
|
|
@ -2291,7 +2328,7 @@ void CSharpScript::update_script_class_info(Ref<CSharpScript> p_script) {
|
|||
|
||||
bool CSharpScript::can_instantiate() const {
|
||||
#ifdef TOOLS_ENABLED
|
||||
bool extra_cond = type_info.is_tool || ScriptServer::is_scripting_enabled();
|
||||
bool extra_cond = (type_info.is_tool || ScriptServer::is_scripting_enabled()) && !Engine::get_singleton()->is_recovery_mode_hint();
|
||||
#else
|
||||
bool extra_cond = true;
|
||||
#endif
|
||||
|
|
@ -2307,9 +2344,7 @@ bool CSharpScript::can_instantiate() const {
|
|||
}
|
||||
|
||||
StringName CSharpScript::get_instance_base_type() const {
|
||||
StringName native_name;
|
||||
GDMonoCache::managed_callbacks.ScriptManagerBridge_GetScriptNativeName(this, &native_name);
|
||||
return native_name;
|
||||
return type_info.native_base_name;
|
||||
}
|
||||
|
||||
CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_is_ref_counted, Callable::CallError &r_error) {
|
||||
|
|
@ -2351,8 +2386,8 @@ CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_arg
|
|||
if (!ok) {
|
||||
// Important to clear this before destroying the script instance here
|
||||
instance->script = Ref<CSharpScript>();
|
||||
instance->owner = nullptr;
|
||||
p_owner->set_script_instance(nullptr);
|
||||
instance->owner = nullptr;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -2707,7 +2742,7 @@ int CSharpScript::get_member_line(const StringName &p_member) const {
|
|||
return -1;
|
||||
}
|
||||
|
||||
const Variant CSharpScript::get_rpc_config() const {
|
||||
Variant CSharpScript::get_rpc_config() const {
|
||||
return rpc_config;
|
||||
}
|
||||
|
||||
|
|
@ -2780,16 +2815,16 @@ Ref<Resource> ResourceFormatLoaderCSharpScript::load(const String &p_path, const
|
|||
if (p_path.begins_with("csharp://")) {
|
||||
// This is a virtual path used by generic types, extract the real path.
|
||||
real_path = "res://" + p_path.trim_prefix("csharp://");
|
||||
real_path = real_path.substr(0, real_path.rfind(":"));
|
||||
real_path = real_path.substr(0, real_path.rfind_char(':'));
|
||||
}
|
||||
|
||||
Ref<CSharpScript> scr;
|
||||
|
||||
if (GDMonoCache::godot_api_cache_updated) {
|
||||
GDMonoCache::managed_callbacks.ScriptManagerBridge_GetOrCreateScriptBridgeForPath(&p_path, &scr);
|
||||
ERR_FAIL_NULL_V_MSG(scr, Ref<Resource>(), "Could not create C# script '" + real_path + "'.");
|
||||
ERR_FAIL_COND_V_MSG(scr.is_null(), Ref<Resource>(), "Could not create C# script '" + real_path + "'.");
|
||||
} else {
|
||||
scr = Ref<CSharpScript>(memnew(CSharpScript));
|
||||
scr.instantiate();
|
||||
}
|
||||
|
||||
#if defined(DEBUG_ENABLED) || defined(TOOLS_ENABLED)
|
||||
|
|
|
|||
|
|
@ -68,6 +68,11 @@ public:
|
|||
*/
|
||||
String class_name;
|
||||
|
||||
/**
|
||||
* Name of the native class this script derives from.
|
||||
*/
|
||||
StringName native_base_name;
|
||||
|
||||
/**
|
||||
* Path to the icon that will be used for this class by the editor.
|
||||
*/
|
||||
|
|
@ -238,6 +243,7 @@ public:
|
|||
void set_source_code(const String &p_code) override;
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
virtual StringName get_doc_class_name() const override { return StringName(); } // TODO
|
||||
virtual Vector<DocData::ClassDoc> get_documentation() const override {
|
||||
// TODO
|
||||
Vector<DocData::ClassDoc> docs;
|
||||
|
|
@ -284,7 +290,7 @@ public:
|
|||
|
||||
int get_member_line(const StringName &p_member) const override;
|
||||
|
||||
const Variant get_rpc_config() const override;
|
||||
Variant get_rpc_config() const override;
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
bool is_placeholder_fallback_enabled() const override {
|
||||
|
|
@ -524,7 +530,7 @@ public:
|
|||
|
||||
/* SCRIPT GLOBAL CLASS FUNCTIONS */
|
||||
virtual bool handles_global_class_type(const String &p_type) const override;
|
||||
virtual String get_global_class_name(const String &p_path, String *r_base_type = nullptr, String *r_icon_path = nullptr) const override;
|
||||
virtual String get_global_class_name(const String &p_path, String *r_base_type = nullptr, String *r_icon_path = nullptr, bool *r_is_abstract = nullptr, bool *r_is_tool = nullptr) const override;
|
||||
|
||||
/* DEBUGGER FUNCTIONS */
|
||||
String debug_get_error() const override;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<Authors>Godot Engine contributors</Authors>
|
||||
|
||||
<PackageId>Godot.NET.Sdk</PackageId>
|
||||
<Version>4.3.0</Version>
|
||||
<Version>4.4.0</Version>
|
||||
<PackageVersion>$(PackageVersion_Godot_NET_Sdk)</PackageVersion>
|
||||
<RepositoryUrl>https://github.com/godotengine/godot/tree/master/modules/mono/editor/Godot.NET.Sdk</RepositoryUrl>
|
||||
<PackageProjectUrl>$(RepositoryUrl)</PackageProjectUrl>
|
||||
|
|
@ -30,6 +30,7 @@
|
|||
<None Include="$(GodotSdkPackageVersionsFilePath)" Pack="true" PackagePath="Sdk">
|
||||
<Link>Sdk\SdkPackageVersions.props</Link>
|
||||
</None>
|
||||
<None Include="Sdk\Android.props" Pack="true" PackagePath="Sdk" />
|
||||
<None Include="Sdk\iOSNativeAOT.props" Pack="true" PackagePath="Sdk" />
|
||||
<None Include="Sdk\iOSNativeAOT.targets" Pack="true" PackagePath="Sdk" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<UseMonoRuntime Condition=" '$(UseMonoRuntime)' == '' and '$(PublishAot)' != 'true' ">true</UseMonoRuntime>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
@ -112,5 +112,6 @@
|
|||
<DefineConstants>$(GodotDefineConstants);$(DefineConstants)</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(MSBuildThisFileDirectory)\Android.props" Condition=" '$(GodotTargetPlatform)' == 'android' " />
|
||||
<Import Project="$(MSBuildThisFileDirectory)\iOSNativeAOT.props" Condition=" '$(GodotTargetPlatform)' == 'ios' " />
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<LangVersion>11</LangVersion>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ public static class CSharpAnalyzerVerifier<TAnalyzer>
|
|||
{
|
||||
public Test()
|
||||
{
|
||||
ReferenceAssemblies = ReferenceAssemblies.Net.Net60;
|
||||
ReferenceAssemblies = Constants.Net80;
|
||||
|
||||
SolutionTransforms.Add((Solution solution, ProjectId projectId) =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ using Microsoft.CodeAnalysis;
|
|||
using Microsoft.CodeAnalysis.CodeFixes;
|
||||
using Microsoft.CodeAnalysis.CSharp.Testing;
|
||||
using Microsoft.CodeAnalysis.Diagnostics;
|
||||
using Microsoft.CodeAnalysis.Testing;
|
||||
using Microsoft.CodeAnalysis.Testing.Verifiers;
|
||||
|
||||
namespace Godot.SourceGenerators.Tests;
|
||||
|
|
@ -17,7 +16,7 @@ public static class CSharpCodeFixVerifier<TCodeFix, TAnalyzer>
|
|||
{
|
||||
public Test()
|
||||
{
|
||||
ReferenceAssemblies = ReferenceAssemblies.Net.Net60;
|
||||
ReferenceAssemblies = Constants.Net80;
|
||||
SolutionTransforms.Add((Solution solution, ProjectId projectId) =>
|
||||
{
|
||||
Project project = solution.GetProject(projectId)!
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ where TSourceGenerator : ISourceGenerator, new()
|
|||
{
|
||||
public Test()
|
||||
{
|
||||
ReferenceAssemblies = ReferenceAssemblies.Net.Net60;
|
||||
ReferenceAssemblies = Constants.Net80;
|
||||
|
||||
SolutionTransforms.Add((Solution solution, ProjectId projectId) =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using System.IO;
|
||||
using System.Reflection;
|
||||
using Microsoft.CodeAnalysis.Testing;
|
||||
|
||||
namespace Godot.SourceGenerators.Tests;
|
||||
|
||||
|
|
@ -7,6 +8,13 @@ public static class Constants
|
|||
{
|
||||
public static Assembly GodotSharpAssembly => typeof(GodotObject).Assembly;
|
||||
|
||||
// Can't find what needs updating to be able to access ReferenceAssemblies.Net.Net80, so we're making our own one.
|
||||
public static ReferenceAssemblies Net80 => new ReferenceAssemblies(
|
||||
"net8.0",
|
||||
new PackageIdentity("Microsoft.NETCore.App.Ref", "8.0.0"),
|
||||
Path.Combine("ref", "net8.0")
|
||||
);
|
||||
|
||||
public static string ExecutingAssemblyPath { get; }
|
||||
public static string SourceFolderPath { get; }
|
||||
public static string GeneratedSourceFolderPath { get; }
|
||||
|
|
|
|||
|
|
@ -74,4 +74,40 @@ public class ExportDiagnosticsTests
|
|||
}
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void ExportToolButtonInNonToolClass()
|
||||
{
|
||||
await CSharpSourceGeneratorVerifier<ScriptPropertiesGenerator>.Verify(
|
||||
new string[] { "ExportDiagnostics_GD0108.cs" },
|
||||
new string[] { "ExportDiagnostics_GD0108_ScriptProperties.generated.cs" }
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void ExportAndExportToolButtonOnSameMember()
|
||||
{
|
||||
await CSharpSourceGeneratorVerifier<ScriptPropertiesGenerator>.Verify(
|
||||
new string[] { "ExportDiagnostics_GD0109.cs" },
|
||||
new string[] { "ExportDiagnostics_GD0109_ScriptProperties.generated.cs" }
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void ExportToolButtonOnNonCallable()
|
||||
{
|
||||
await CSharpSourceGeneratorVerifier<ScriptPropertiesGenerator>.Verify(
|
||||
new string[] { "ExportDiagnostics_GD0110.cs" },
|
||||
new string[] { "ExportDiagnostics_GD0110_ScriptProperties.generated.cs" }
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void ExportToolButtonStoringCallable()
|
||||
{
|
||||
await CSharpSourceGeneratorVerifier<ScriptPropertiesGenerator>.Verify(
|
||||
new string[] { "ExportDiagnostics_GD0111.cs" },
|
||||
new string[] { "ExportDiagnostics_GD0111_ScriptProperties.generated.cs" }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
|
||||
<LangVersion>11</LangVersion>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
|
|
|
|||
|
|
@ -66,4 +66,13 @@ public class ScriptPropertiesGeneratorTests
|
|||
"AbstractGenericNode(Of T)_ScriptProperties.generated.cs"
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void ExportedButtons()
|
||||
{
|
||||
await CSharpSourceGeneratorVerifier<ScriptPropertiesGenerator>.Verify(
|
||||
"ExportedToolButtons.cs",
|
||||
"ExportedToolButtons_ScriptProperties.generated.cs"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,10 @@ partial class EventSignals
|
|||
add => backing_MySignal += value;
|
||||
remove => backing_MySignal -= value;
|
||||
}
|
||||
protected void EmitSignalMySignal(string @str, int @num)
|
||||
{
|
||||
EmitSignal(SignalName.MySignal, @str, @num);
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||
protected override void RaiseGodotClassSignalCallbacks(in godot_string_name signal, NativeVariantPtrArgs args)
|
||||
|
|
|
|||
|
|
@ -11,11 +11,27 @@ partial class ExportDiagnostics_GD0107_OK
|
|||
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||
internal new static global::System.Collections.Generic.Dictionary<global::Godot.StringName, global::Godot.Variant> GetGodotPropertyDefaultValues()
|
||||
{
|
||||
var values = new global::System.Collections.Generic.Dictionary<global::Godot.StringName, global::Godot.Variant>(2);
|
||||
var values = new global::System.Collections.Generic.Dictionary<global::Godot.StringName, global::Godot.Variant>(10);
|
||||
global::Godot.Node __NodeProperty_default_value = default;
|
||||
values.Add(PropertyName.@NodeProperty, global::Godot.Variant.From<global::Godot.Node>(__NodeProperty_default_value));
|
||||
global::Godot.Node[] __SystemArrayOfNodesProperty_default_value = default;
|
||||
values.Add(PropertyName.@SystemArrayOfNodesProperty, global::Godot.Variant.CreateFrom(__SystemArrayOfNodesProperty_default_value));
|
||||
global::Godot.Collections.Array<global::Godot.Node> __GodotArrayOfNodesProperty_default_value = default;
|
||||
values.Add(PropertyName.@GodotArrayOfNodesProperty, global::Godot.Variant.CreateFrom(__GodotArrayOfNodesProperty_default_value));
|
||||
global::Godot.Collections.Dictionary<global::Godot.Node, string> __GodotDictionaryWithNodeAsKeyProperty_default_value = default;
|
||||
values.Add(PropertyName.@GodotDictionaryWithNodeAsKeyProperty, global::Godot.Variant.CreateFrom(__GodotDictionaryWithNodeAsKeyProperty_default_value));
|
||||
global::Godot.Collections.Dictionary<string, global::Godot.Node> __GodotDictionaryWithNodeAsValueProperty_default_value = default;
|
||||
values.Add(PropertyName.@GodotDictionaryWithNodeAsValueProperty, global::Godot.Variant.CreateFrom(__GodotDictionaryWithNodeAsValueProperty_default_value));
|
||||
global::Godot.Node __NodeField_default_value = default;
|
||||
values.Add(PropertyName.@NodeField, global::Godot.Variant.From<global::Godot.Node>(__NodeField_default_value));
|
||||
global::Godot.Node[] __SystemArrayOfNodesField_default_value = default;
|
||||
values.Add(PropertyName.@SystemArrayOfNodesField, global::Godot.Variant.CreateFrom(__SystemArrayOfNodesField_default_value));
|
||||
global::Godot.Collections.Array<global::Godot.Node> __GodotArrayOfNodesField_default_value = default;
|
||||
values.Add(PropertyName.@GodotArrayOfNodesField, global::Godot.Variant.CreateFrom(__GodotArrayOfNodesField_default_value));
|
||||
global::Godot.Collections.Dictionary<global::Godot.Node, string> __GodotDictionaryWithNodeAsKeyField_default_value = default;
|
||||
values.Add(PropertyName.@GodotDictionaryWithNodeAsKeyField, global::Godot.Variant.CreateFrom(__GodotDictionaryWithNodeAsKeyField_default_value));
|
||||
global::Godot.Collections.Dictionary<string, global::Godot.Node> __GodotDictionaryWithNodeAsValueField_default_value = default;
|
||||
values.Add(PropertyName.@GodotDictionaryWithNodeAsValueField, global::Godot.Variant.CreateFrom(__GodotDictionaryWithNodeAsValueField_default_value));
|
||||
return values;
|
||||
}
|
||||
#endif // TOOLS
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
using Godot;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
partial class ExportDiagnostics_GD0108
|
||||
{
|
||||
#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword
|
||||
/// <summary>
|
||||
/// Cached StringNames for the properties and fields contained in this class, for fast lookup.
|
||||
/// </summary>
|
||||
public new class PropertyName : global::Godot.Node.PropertyName {
|
||||
/// <summary>
|
||||
/// Cached name for the 'MyButton' property.
|
||||
/// </summary>
|
||||
public new static readonly global::Godot.StringName @MyButton = "MyButton";
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||
protected override bool GetGodotClassPropertyValue(in godot_string_name name, out godot_variant value)
|
||||
{
|
||||
if (name == PropertyName.@MyButton) {
|
||||
value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this.@MyButton);
|
||||
return true;
|
||||
}
|
||||
return base.GetGodotClassPropertyValue(name, out value);
|
||||
}
|
||||
/// <summary>
|
||||
/// Get the property information for all the properties declared in this class.
|
||||
/// This method is used by Godot to register the available properties in the editor.
|
||||
/// Do not call this method.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||
internal new static global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo> GetGodotPropertyList()
|
||||
{
|
||||
var properties = new global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>();
|
||||
return properties;
|
||||
}
|
||||
#pragma warning restore CS0109
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
using Godot;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
partial class ExportDiagnostics_GD0109
|
||||
{
|
||||
#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword
|
||||
/// <summary>
|
||||
/// Cached StringNames for the properties and fields contained in this class, for fast lookup.
|
||||
/// </summary>
|
||||
public new class PropertyName : global::Godot.Node.PropertyName {
|
||||
/// <summary>
|
||||
/// Cached name for the 'MyButton' property.
|
||||
/// </summary>
|
||||
public new static readonly global::Godot.StringName @MyButton = "MyButton";
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||
protected override bool GetGodotClassPropertyValue(in godot_string_name name, out godot_variant value)
|
||||
{
|
||||
if (name == PropertyName.@MyButton) {
|
||||
value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this.@MyButton);
|
||||
return true;
|
||||
}
|
||||
return base.GetGodotClassPropertyValue(name, out value);
|
||||
}
|
||||
/// <summary>
|
||||
/// Get the property information for all the properties declared in this class.
|
||||
/// This method is used by Godot to register the available properties in the editor.
|
||||
/// Do not call this method.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||
internal new static global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo> GetGodotPropertyList()
|
||||
{
|
||||
var properties = new global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>();
|
||||
return properties;
|
||||
}
|
||||
#pragma warning restore CS0109
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
using Godot;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
partial class ExportDiagnostics_GD0110
|
||||
{
|
||||
#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword
|
||||
/// <summary>
|
||||
/// Cached StringNames for the properties and fields contained in this class, for fast lookup.
|
||||
/// </summary>
|
||||
public new class PropertyName : global::Godot.Node.PropertyName {
|
||||
/// <summary>
|
||||
/// Cached name for the 'MyButton' property.
|
||||
/// </summary>
|
||||
public new static readonly global::Godot.StringName @MyButton = "MyButton";
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||
protected override bool GetGodotClassPropertyValue(in godot_string_name name, out godot_variant value)
|
||||
{
|
||||
if (name == PropertyName.@MyButton) {
|
||||
value = global::Godot.NativeInterop.VariantUtils.CreateFrom<int>(this.@MyButton);
|
||||
return true;
|
||||
}
|
||||
return base.GetGodotClassPropertyValue(name, out value);
|
||||
}
|
||||
/// <summary>
|
||||
/// Get the property information for all the properties declared in this class.
|
||||
/// This method is used by Godot to register the available properties in the editor.
|
||||
/// Do not call this method.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||
internal new static global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo> GetGodotPropertyList()
|
||||
{
|
||||
var properties = new global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>();
|
||||
return properties;
|
||||
}
|
||||
#pragma warning restore CS0109
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
using Godot;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
partial class ExportDiagnostics_GD0111
|
||||
{
|
||||
#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword
|
||||
/// <summary>
|
||||
/// Cached StringNames for the properties and fields contained in this class, for fast lookup.
|
||||
/// </summary>
|
||||
public new class PropertyName : global::Godot.Node.PropertyName {
|
||||
/// <summary>
|
||||
/// Cached name for the 'MyButtonGet' property.
|
||||
/// </summary>
|
||||
public new static readonly global::Godot.StringName @MyButtonGet = "MyButtonGet";
|
||||
/// <summary>
|
||||
/// Cached name for the 'MyButtonGetSet' property.
|
||||
/// </summary>
|
||||
public new static readonly global::Godot.StringName @MyButtonGetSet = "MyButtonGetSet";
|
||||
/// <summary>
|
||||
/// Cached name for the 'MyButtonGetWithBackingField' property.
|
||||
/// </summary>
|
||||
public new static readonly global::Godot.StringName @MyButtonGetWithBackingField = "MyButtonGetWithBackingField";
|
||||
/// <summary>
|
||||
/// Cached name for the 'MyButtonGetSetWithBackingField' property.
|
||||
/// </summary>
|
||||
public new static readonly global::Godot.StringName @MyButtonGetSetWithBackingField = "MyButtonGetSetWithBackingField";
|
||||
/// <summary>
|
||||
/// Cached name for the 'MyButtonOkWithCallableCreationExpression' property.
|
||||
/// </summary>
|
||||
public new static readonly global::Godot.StringName @MyButtonOkWithCallableCreationExpression = "MyButtonOkWithCallableCreationExpression";
|
||||
/// <summary>
|
||||
/// Cached name for the 'MyButtonOkWithImplicitCallableCreationExpression' property.
|
||||
/// </summary>
|
||||
public new static readonly global::Godot.StringName @MyButtonOkWithImplicitCallableCreationExpression = "MyButtonOkWithImplicitCallableCreationExpression";
|
||||
/// <summary>
|
||||
/// Cached name for the 'MyButtonOkWithCallableFromExpression' property.
|
||||
/// </summary>
|
||||
public new static readonly global::Godot.StringName @MyButtonOkWithCallableFromExpression = "MyButtonOkWithCallableFromExpression";
|
||||
/// <summary>
|
||||
/// Cached name for the '_backingField' field.
|
||||
/// </summary>
|
||||
public new static readonly global::Godot.StringName @_backingField = "_backingField";
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||
protected override bool SetGodotClassPropertyValue(in godot_string_name name, in godot_variant value)
|
||||
{
|
||||
if (name == PropertyName.@MyButtonGetSet) {
|
||||
this.@MyButtonGetSet = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Callable>(value);
|
||||
return true;
|
||||
}
|
||||
if (name == PropertyName.@MyButtonGetSetWithBackingField) {
|
||||
this.@MyButtonGetSetWithBackingField = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Callable>(value);
|
||||
return true;
|
||||
}
|
||||
if (name == PropertyName.@_backingField) {
|
||||
this.@_backingField = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Callable>(value);
|
||||
return true;
|
||||
}
|
||||
return base.SetGodotClassPropertyValue(name, value);
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||
protected override bool GetGodotClassPropertyValue(in godot_string_name name, out godot_variant value)
|
||||
{
|
||||
if (name == PropertyName.@MyButtonGet) {
|
||||
value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this.@MyButtonGet);
|
||||
return true;
|
||||
}
|
||||
if (name == PropertyName.@MyButtonGetSet) {
|
||||
value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this.@MyButtonGetSet);
|
||||
return true;
|
||||
}
|
||||
if (name == PropertyName.@MyButtonGetWithBackingField) {
|
||||
value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this.@MyButtonGetWithBackingField);
|
||||
return true;
|
||||
}
|
||||
if (name == PropertyName.@MyButtonGetSetWithBackingField) {
|
||||
value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this.@MyButtonGetSetWithBackingField);
|
||||
return true;
|
||||
}
|
||||
if (name == PropertyName.@MyButtonOkWithCallableCreationExpression) {
|
||||
value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this.@MyButtonOkWithCallableCreationExpression);
|
||||
return true;
|
||||
}
|
||||
if (name == PropertyName.@MyButtonOkWithImplicitCallableCreationExpression) {
|
||||
value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this.@MyButtonOkWithImplicitCallableCreationExpression);
|
||||
return true;
|
||||
}
|
||||
if (name == PropertyName.@MyButtonOkWithCallableFromExpression) {
|
||||
value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this.@MyButtonOkWithCallableFromExpression);
|
||||
return true;
|
||||
}
|
||||
if (name == PropertyName.@_backingField) {
|
||||
value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this.@_backingField);
|
||||
return true;
|
||||
}
|
||||
return base.GetGodotClassPropertyValue(name, out value);
|
||||
}
|
||||
/// <summary>
|
||||
/// Get the property information for all the properties declared in this class.
|
||||
/// This method is used by Godot to register the available properties in the editor.
|
||||
/// Do not call this method.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||
internal new static global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo> GetGodotPropertyList()
|
||||
{
|
||||
var properties = new global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>();
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)25, name: PropertyName.@_backingField, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)25, name: PropertyName.@MyButtonOkWithCallableCreationExpression, hint: (global::Godot.PropertyHint)39, hintString: "", usage: (global::Godot.PropertyUsageFlags)4, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)25, name: PropertyName.@MyButtonOkWithImplicitCallableCreationExpression, hint: (global::Godot.PropertyHint)39, hintString: "", usage: (global::Godot.PropertyUsageFlags)4, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)25, name: PropertyName.@MyButtonOkWithCallableFromExpression, hint: (global::Godot.PropertyHint)39, hintString: "", usage: (global::Godot.PropertyUsageFlags)4, exported: true));
|
||||
return properties;
|
||||
}
|
||||
#pragma warning restore CS0109
|
||||
}
|
||||
|
|
@ -807,7 +807,7 @@ partial class ExportedFields
|
|||
properties.Add(new(type: (global::Godot.Variant.Type)23, name: PropertyName.@_fieldRid, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@_fieldGodotDictionary, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.@_fieldGodotArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@_fieldGodotGenericDictionary, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@_fieldGodotGenericDictionary, hint: (global::Godot.PropertyHint)23, hintString: "4/0:;1/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.@_fieldGodotGenericArray, hint: (global::Godot.PropertyHint)23, hintString: "2/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)31, name: PropertyName.@_fieldEmptyInt64Array, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
return properties;
|
||||
|
|
|
|||
|
|
@ -925,7 +925,7 @@ partial class ExportedProperties
|
|||
properties.Add(new(type: (global::Godot.Variant.Type)23, name: PropertyName.@PropertyRid, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@PropertyGodotDictionary, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.@PropertyGodotArray, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@PropertyGodotGenericDictionary, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)27, name: PropertyName.@PropertyGodotGenericDictionary, hint: (global::Godot.PropertyHint)23, hintString: "4/0:;1/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)28, name: PropertyName.@PropertyGodotGenericArray, hint: (global::Godot.PropertyHint)23, hintString: "2/0:", usage: (global::Godot.PropertyUsageFlags)4102, exported: true));
|
||||
return properties;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
using Godot;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
partial class ExportedToolButtons
|
||||
{
|
||||
#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword
|
||||
/// <summary>
|
||||
/// Cached StringNames for the properties and fields contained in this class, for fast lookup.
|
||||
/// </summary>
|
||||
public new class PropertyName : global::Godot.GodotObject.PropertyName {
|
||||
/// <summary>
|
||||
/// Cached name for the 'MyButton1' property.
|
||||
/// </summary>
|
||||
public new static readonly global::Godot.StringName @MyButton1 = "MyButton1";
|
||||
/// <summary>
|
||||
/// Cached name for the 'MyButton2' property.
|
||||
/// </summary>
|
||||
public new static readonly global::Godot.StringName @MyButton2 = "MyButton2";
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||
protected override bool GetGodotClassPropertyValue(in godot_string_name name, out godot_variant value)
|
||||
{
|
||||
if (name == PropertyName.@MyButton1) {
|
||||
value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this.@MyButton1);
|
||||
return true;
|
||||
}
|
||||
if (name == PropertyName.@MyButton2) {
|
||||
value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this.@MyButton2);
|
||||
return true;
|
||||
}
|
||||
return base.GetGodotClassPropertyValue(name, out value);
|
||||
}
|
||||
/// <summary>
|
||||
/// Get the property information for all the properties declared in this class.
|
||||
/// This method is used by Godot to register the available properties in the editor.
|
||||
/// Do not call this method.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||
internal new static global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo> GetGodotPropertyList()
|
||||
{
|
||||
var properties = new global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>();
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)25, name: PropertyName.@MyButton1, hint: (global::Godot.PropertyHint)39, hintString: "Click me!", usage: (global::Godot.PropertyUsageFlags)4, exported: true));
|
||||
properties.Add(new(type: (global::Godot.Variant.Type)25, name: PropertyName.@MyButton2, hint: (global::Godot.PropertyHint)39, hintString: "Click me!,ColorRect", usage: (global::Godot.PropertyUsageFlags)4, exported: true));
|
||||
return properties;
|
||||
}
|
||||
#pragma warning restore CS0109
|
||||
}
|
||||
|
|
@ -1,12 +1,37 @@
|
|||
using Godot;
|
||||
using Godot.Collections;
|
||||
|
||||
public partial class ExportDiagnostics_GD0107_OK : Node
|
||||
{
|
||||
[Export]
|
||||
public Node NodeField;
|
||||
|
||||
[Export]
|
||||
public Node[] SystemArrayOfNodesField;
|
||||
|
||||
[Export]
|
||||
public Array<Node> GodotArrayOfNodesField;
|
||||
|
||||
[Export]
|
||||
public Dictionary<Node, string> GodotDictionaryWithNodeAsKeyField;
|
||||
|
||||
[Export]
|
||||
public Dictionary<string, Node> GodotDictionaryWithNodeAsValueField;
|
||||
|
||||
[Export]
|
||||
public Node NodeProperty { get; set; }
|
||||
|
||||
[Export]
|
||||
public Node[] SystemArrayOfNodesProperty { get; set; }
|
||||
|
||||
[Export]
|
||||
public Array<Node> GodotArrayOfNodesProperty { get; set; }
|
||||
|
||||
[Export]
|
||||
public Dictionary<Node, string> GodotDictionaryWithNodeAsKeyProperty { get; set; }
|
||||
|
||||
[Export]
|
||||
public Dictionary<string, Node> GodotDictionaryWithNodeAsValueProperty { get; set; }
|
||||
}
|
||||
|
||||
public partial class ExportDiagnostics_GD0107_KO : Resource
|
||||
|
|
@ -14,6 +39,30 @@ public partial class ExportDiagnostics_GD0107_KO : Resource
|
|||
[Export]
|
||||
public Node {|GD0107:NodeField|};
|
||||
|
||||
[Export]
|
||||
public Node[] {|GD0107:SystemArrayOfNodesField|};
|
||||
|
||||
[Export]
|
||||
public Array<Node> {|GD0107:GodotArrayOfNodesField|};
|
||||
|
||||
[Export]
|
||||
public Dictionary<Node, string> {|GD0107:GodotDictionaryWithNodeAsKeyField|};
|
||||
|
||||
[Export]
|
||||
public Dictionary<string, Node> {|GD0107:GodotDictionaryWithNodeAsValueField|};
|
||||
|
||||
[Export]
|
||||
public Node {|GD0107:NodeProperty|} { get; set; }
|
||||
|
||||
[Export]
|
||||
public Node[] {|GD0107:SystemArrayOfNodesProperty|} { get; set; }
|
||||
|
||||
[Export]
|
||||
public Array<Node> {|GD0107:GodotArrayOfNodesProperty|} { get; set; }
|
||||
|
||||
[Export]
|
||||
public Dictionary<Node, string> {|GD0107:GodotDictionaryWithNodeAsKeyProperty|} { get; set; }
|
||||
|
||||
[Export]
|
||||
public Dictionary<string, Node> {|GD0107:GodotDictionaryWithNodeAsValueProperty|} { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
using Godot;
|
||||
using Godot.Collections;
|
||||
|
||||
public partial class ExportDiagnostics_GD0108 : Node
|
||||
{
|
||||
[ExportToolButton("")]
|
||||
public Callable {|GD0108:MyButton|} => new Callable();
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
using Godot;
|
||||
using Godot.Collections;
|
||||
|
||||
[Tool]
|
||||
public partial class ExportDiagnostics_GD0109 : Node
|
||||
{
|
||||
[Export, ExportToolButton("")]
|
||||
public Callable {|GD0109:MyButton|} => new Callable();
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
using Godot;
|
||||
using Godot.Collections;
|
||||
|
||||
[Tool]
|
||||
public partial class ExportDiagnostics_GD0110 : Node
|
||||
{
|
||||
[ExportToolButton("")]
|
||||
public int {|GD0110:MyButton|} => new();
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
using Godot;
|
||||
using Godot.Collections;
|
||||
|
||||
[Tool]
|
||||
public partial class ExportDiagnostics_GD0111 : Node
|
||||
{
|
||||
private Callable _backingField;
|
||||
|
||||
[ExportToolButton("")]
|
||||
public Callable {|GD0111:MyButtonGet|} { get; }
|
||||
|
||||
[ExportToolButton("")]
|
||||
public Callable {|GD0111:MyButtonGetSet|} { get; set; }
|
||||
|
||||
[ExportToolButton("")]
|
||||
public Callable {|GD0111:MyButtonGetWithBackingField|} { get => _backingField; }
|
||||
|
||||
[ExportToolButton("")]
|
||||
public Callable {|GD0111:MyButtonGetSetWithBackingField|} { get => _backingField; set => _backingField = value; }
|
||||
|
||||
[ExportToolButton("")]
|
||||
public Callable MyButtonOkWithCallableCreationExpression => new Callable(this, "");
|
||||
|
||||
[ExportToolButton("")]
|
||||
public Callable MyButtonOkWithImplicitCallableCreationExpression => new(this, "");
|
||||
|
||||
[ExportToolButton("")]
|
||||
public Callable MyButtonOkWithCallableFromExpression => Callable.From(null);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
using Godot;
|
||||
using System;
|
||||
|
||||
[Tool]
|
||||
public partial class ExportedToolButtons : GodotObject
|
||||
{
|
||||
[ExportToolButton("Click me!")]
|
||||
public Callable MyButton1 => Callable.From(() => { GD.Print("Clicked MyButton1!"); });
|
||||
|
||||
[ExportToolButton("Click me!", Icon = "ColorRect")]
|
||||
public Callable MyButton2 => Callable.From(() => { GD.Print("Clicked MyButton2!"); });
|
||||
}
|
||||
|
|
@ -395,6 +395,11 @@ public class MustBeVariantAnnotatedMethods
|
|||
public void MethodWithWrongAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
[NestedGenericTypeAttributeContainer.NestedGenericTypeAttribute<bool>()]
|
||||
public void MethodWithNestedAttribute()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[GenericTypeAttribute<bool>()]
|
||||
|
|
@ -657,3 +662,11 @@ public class ClassNonVariantAnnotated
|
|||
public class GenericTypeAttribute<[MustBeVariant] T> : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
public class NestedGenericTypeAttributeContainer
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
|
||||
public class NestedGenericTypeAttribute<[MustBeVariant] T> : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,3 +3,7 @@
|
|||
Rule ID | Category | Severity | Notes
|
||||
--------|----------|----------|--------------------
|
||||
GD0003 | Usage | Error | ScriptPathAttributeGenerator, [Documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/c_sharp/diagnostics/GD0003.html)
|
||||
GD0108 | Usage | Error | ScriptPropertiesGenerator, [Documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/c_sharp/diagnostics/GD0108.html)
|
||||
GD0109 | Usage | Error | ScriptPropertiesGenerator, [Documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/c_sharp/diagnostics/GD0109.html)
|
||||
GD0110 | Usage | Error | ScriptPropertiesGenerator, [Documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/c_sharp/diagnostics/GD0110.html)
|
||||
GD0111 | Usage | Error | ScriptPropertiesGenerator, [Documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/c_sharp/diagnostics/GD0111.html)
|
||||
|
|
|
|||
|
|
@ -107,6 +107,46 @@ namespace Godot.SourceGenerators
|
|||
"Types not derived from Node should not export Node members. Node export is only supported in Node-derived classes.",
|
||||
helpLinkUri: string.Format(_helpLinkFormat, "GD0107"));
|
||||
|
||||
public static readonly DiagnosticDescriptor OnlyToolClassesShouldUseExportToolButtonRule =
|
||||
new DiagnosticDescriptor(id: "GD0108",
|
||||
title: "The exported tool button is not in a tool class",
|
||||
messageFormat: "The exported tool button '{0}' is not in a tool class",
|
||||
category: "Usage",
|
||||
DiagnosticSeverity.Error,
|
||||
isEnabledByDefault: true,
|
||||
"The exported tool button is not in a tool class. Annotate the class with the '[Tool]' attribute, or remove the '[ExportToolButton]' attribute.",
|
||||
helpLinkUri: string.Format(_helpLinkFormat, "GD0108"));
|
||||
|
||||
public static readonly DiagnosticDescriptor ExportToolButtonShouldNotBeUsedWithExportRule =
|
||||
new DiagnosticDescriptor(id: "GD0109",
|
||||
title: "The '[ExportToolButton]' attribute cannot be used with another '[Export]' attribute",
|
||||
messageFormat: "The '[ExportToolButton]' attribute cannot be used with another '[Export]' attribute on '{0}'",
|
||||
category: "Usage",
|
||||
DiagnosticSeverity.Error,
|
||||
isEnabledByDefault: true,
|
||||
"The '[ExportToolButton]' attribute cannot be used with the '[Export]' attribute. Remove one of the attributes.",
|
||||
helpLinkUri: string.Format(_helpLinkFormat, "GD0109"));
|
||||
|
||||
public static readonly DiagnosticDescriptor ExportToolButtonIsNotCallableRule =
|
||||
new DiagnosticDescriptor(id: "GD0110",
|
||||
title: "The exported tool button is not a Callable",
|
||||
messageFormat: "The exported tool button '{0}' is not a Callable",
|
||||
category: "Usage",
|
||||
DiagnosticSeverity.Error,
|
||||
isEnabledByDefault: true,
|
||||
"The exported tool button is not a Callable. The '[ExportToolButton]' attribute is only supported on members of type Callable.",
|
||||
helpLinkUri: string.Format(_helpLinkFormat, "GD0110"));
|
||||
|
||||
public static readonly DiagnosticDescriptor ExportToolButtonMustBeExpressionBodiedProperty =
|
||||
new DiagnosticDescriptor(id: "GD0111",
|
||||
title: "The exported tool button must be an expression-bodied property",
|
||||
messageFormat: "The exported tool button '{0}' must be an expression-bodied property",
|
||||
category: "Usage",
|
||||
DiagnosticSeverity.Error,
|
||||
isEnabledByDefault: true,
|
||||
"The exported tool button must be an expression-bodied property. The '[ExportToolButton]' attribute is only supported on expression-bodied properties with a 'new Callable(...)' or 'Callable.From(...)' expression.",
|
||||
helpLinkUri: string.Format(_helpLinkFormat, "GD0111"));
|
||||
|
||||
public static readonly DiagnosticDescriptor SignalDelegateMissingSuffixRule =
|
||||
new DiagnosticDescriptor(id: "GD0201",
|
||||
title: "The name of the delegate must end with 'EventHandler'",
|
||||
|
|
|
|||
|
|
@ -155,6 +155,32 @@ namespace Godot.SourceGenerators
|
|||
};
|
||||
}
|
||||
|
||||
public static string GetAccessibilityKeyword(this INamedTypeSymbol namedTypeSymbol)
|
||||
{
|
||||
if (namedTypeSymbol.DeclaredAccessibility == Accessibility.NotApplicable)
|
||||
{
|
||||
// Accessibility not specified. Get the default accessibility.
|
||||
return namedTypeSymbol.ContainingSymbol switch
|
||||
{
|
||||
null or INamespaceSymbol => "internal",
|
||||
ITypeSymbol { TypeKind: TypeKind.Class or TypeKind.Struct } => "private",
|
||||
ITypeSymbol { TypeKind: TypeKind.Interface } => "public",
|
||||
_ => "",
|
||||
};
|
||||
}
|
||||
|
||||
return namedTypeSymbol.DeclaredAccessibility switch
|
||||
{
|
||||
Accessibility.Private => "private",
|
||||
Accessibility.Protected => "protected",
|
||||
Accessibility.Internal => "internal",
|
||||
Accessibility.ProtectedAndInternal => "private",
|
||||
Accessibility.ProtectedOrInternal => "private",
|
||||
Accessibility.Public => "public",
|
||||
_ => "",
|
||||
};
|
||||
}
|
||||
|
||||
public static string NameWithTypeParameters(this INamedTypeSymbol symbol)
|
||||
{
|
||||
return symbol.IsGenericType ?
|
||||
|
|
@ -261,6 +287,12 @@ namespace Godot.SourceGenerators
|
|||
public static bool IsGodotGlobalClassAttribute(this INamedTypeSymbol symbol)
|
||||
=> symbol.FullQualifiedNameOmitGlobal() == GodotClasses.GlobalClassAttr;
|
||||
|
||||
public static bool IsGodotExportToolButtonAttribute(this INamedTypeSymbol symbol)
|
||||
=> symbol.FullQualifiedNameOmitGlobal() == GodotClasses.ExportToolButtonAttr;
|
||||
|
||||
public static bool IsGodotToolAttribute(this INamedTypeSymbol symbol)
|
||||
=> symbol.FullQualifiedNameOmitGlobal() == GodotClasses.ToolAttr;
|
||||
|
||||
public static bool IsSystemFlagsAttribute(this INamedTypeSymbol symbol)
|
||||
=> symbol.FullQualifiedNameOmitGlobal() == GodotClasses.SystemFlagsAttr;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,13 +3,14 @@
|
|||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<LangVersion>10</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<Description>Core C# source generator for Godot projects.</Description>
|
||||
<Authors>Godot Engine contributors</Authors>
|
||||
|
||||
<PackageId>Godot.SourceGenerators</PackageId>
|
||||
<Version>4.3.0</Version>
|
||||
<Version>4.4.0</Version>
|
||||
<PackageVersion>$(PackageVersion_Godot_SourceGenerators)</PackageVersion>
|
||||
<RepositoryUrl>https://github.com/godotengine/godot/tree/master/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators</RepositoryUrl>
|
||||
<PackageProjectUrl>$(RepositoryUrl)</PackageProjectUrl>
|
||||
|
|
|
|||
|
|
@ -4,15 +4,18 @@ namespace Godot.SourceGenerators
|
|||
{
|
||||
public const string GodotObject = "Godot.GodotObject";
|
||||
public const string Node = "Godot.Node";
|
||||
public const string Callable = "Godot.Callable";
|
||||
public const string AssemblyHasScriptsAttr = "Godot.AssemblyHasScriptsAttribute";
|
||||
public const string ExportAttr = "Godot.ExportAttribute";
|
||||
public const string ExportCategoryAttr = "Godot.ExportCategoryAttribute";
|
||||
public const string ExportGroupAttr = "Godot.ExportGroupAttribute";
|
||||
public const string ExportSubgroupAttr = "Godot.ExportSubgroupAttribute";
|
||||
public const string ExportToolButtonAttr = "Godot.ExportToolButtonAttribute";
|
||||
public const string SignalAttr = "Godot.SignalAttribute";
|
||||
public const string MustBeVariantAttr = "Godot.MustBeVariantAttribute";
|
||||
public const string GodotClassNameAttr = "Godot.GodotClassNameAttribute";
|
||||
public const string GlobalClassAttr = "Godot.GlobalClassAttribute";
|
||||
public const string ToolAttr = "Godot.ToolAttribute";
|
||||
public const string SystemFlagsAttr = "System.FlagsAttribute";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,7 +88,9 @@ namespace Godot.SourceGenerators
|
|||
HideQuaternionEdit = 35,
|
||||
Password = 36,
|
||||
LayersAvoidance = 37,
|
||||
Max = 38
|
||||
DictionaryType = 38,
|
||||
ToolButton = 39,
|
||||
Max = 40
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
|
|
|||
|
|
@ -274,6 +274,14 @@ namespace Godot.SourceGenerators
|
|||
return null;
|
||||
}
|
||||
|
||||
public static ITypeSymbol[]? GetGenericElementTypes(ITypeSymbol typeSymbol)
|
||||
{
|
||||
if (typeSymbol is INamedTypeSymbol { IsGenericType: true } genericType)
|
||||
return genericType.TypeArguments.ToArray();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static StringBuilder Append(this StringBuilder source, string a, string b)
|
||||
=> source.Append(a).Append(b);
|
||||
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ namespace Godot.SourceGenerators
|
|||
{
|
||||
ITypeParameterSymbol? typeParamSymbol = parentSymbol switch
|
||||
{
|
||||
IMethodSymbol methodSymbol when parentSyntax.Parent is AttributeSyntax &&
|
||||
IMethodSymbol methodSymbol when parentSyntax.Ancestors().Any(s => s is AttributeSyntax) &&
|
||||
methodSymbol.ContainingType.TypeParameters.Length > 0
|
||||
=> methodSymbol.ContainingType.TypeParameters[typeArgumentIndex],
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
|
||||
|
|
@ -68,6 +70,7 @@ namespace Godot.SourceGenerators
|
|||
bool hasNamespace = classNs.Length != 0;
|
||||
|
||||
bool isInnerClass = symbol.ContainingType != null;
|
||||
bool isToolClass = symbol.GetAttributes().Any(a => a.AttributeClass?.IsGodotToolAttribute() ?? false);
|
||||
|
||||
string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint()
|
||||
+ "_ScriptProperties.generated";
|
||||
|
|
@ -276,6 +279,16 @@ namespace Godot.SourceGenerators
|
|||
if (propertyInfo == null)
|
||||
continue;
|
||||
|
||||
if (propertyInfo.Value.Hint == PropertyHint.ToolButton && !isToolClass)
|
||||
{
|
||||
context.ReportDiagnostic(Diagnostic.Create(
|
||||
Common.OnlyToolClassesShouldUseExportToolButtonRule,
|
||||
member.Symbol.Locations.FirstLocationWithSourceTreeOrDefault(),
|
||||
member.Symbol.ToDisplayString()
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
||||
AppendPropertyInfo(source, propertyInfo.Value);
|
||||
}
|
||||
|
||||
|
|
@ -417,31 +430,127 @@ namespace Godot.SourceGenerators
|
|||
var exportAttr = memberSymbol.GetAttributes()
|
||||
.FirstOrDefault(a => a.AttributeClass?.IsGodotExportAttribute() ?? false);
|
||||
|
||||
var exportToolButtonAttr = memberSymbol.GetAttributes()
|
||||
.FirstOrDefault(a => a.AttributeClass?.IsGodotExportToolButtonAttribute() ?? false);
|
||||
|
||||
if (exportAttr != null && exportToolButtonAttr != null)
|
||||
{
|
||||
context.ReportDiagnostic(Diagnostic.Create(
|
||||
Common.ExportToolButtonShouldNotBeUsedWithExportRule,
|
||||
memberSymbol.Locations.FirstLocationWithSourceTreeOrDefault(),
|
||||
memberSymbol.ToDisplayString()
|
||||
));
|
||||
return null;
|
||||
}
|
||||
|
||||
var propertySymbol = memberSymbol as IPropertySymbol;
|
||||
var fieldSymbol = memberSymbol as IFieldSymbol;
|
||||
|
||||
if (exportAttr != null && propertySymbol != null)
|
||||
{
|
||||
if (propertySymbol.GetMethod == null)
|
||||
if (propertySymbol.GetMethod == null || propertySymbol.SetMethod == null || propertySymbol.SetMethod.IsInitOnly)
|
||||
{
|
||||
// Exports can be neither read-only nor write-only but the diagnostic errors for properties are already
|
||||
// reported by ScriptPropertyDefValGenerator.cs so just quit early here.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (exportToolButtonAttr != null && propertySymbol != null && propertySymbol.GetMethod == null)
|
||||
{
|
||||
context.ReportDiagnostic(Diagnostic.Create(
|
||||
Common.ExportedPropertyIsWriteOnlyRule,
|
||||
propertySymbol.Locations.FirstLocationWithSourceTreeOrDefault(),
|
||||
propertySymbol.ToDisplayString()
|
||||
));
|
||||
return null;
|
||||
}
|
||||
|
||||
if (exportToolButtonAttr != null && propertySymbol != null)
|
||||
{
|
||||
if (!PropertyIsExpressionBodiedAndReturnsNewCallable(context.Compilation, propertySymbol))
|
||||
{
|
||||
// This should never happen, as we filtered WriteOnly properties, but just in case.
|
||||
context.ReportDiagnostic(Diagnostic.Create(
|
||||
Common.ExportedPropertyIsWriteOnlyRule,
|
||||
Common.ExportToolButtonMustBeExpressionBodiedProperty,
|
||||
propertySymbol.Locations.FirstLocationWithSourceTreeOrDefault(),
|
||||
propertySymbol.ToDisplayString()
|
||||
));
|
||||
return null;
|
||||
}
|
||||
|
||||
if (propertySymbol.SetMethod == null || propertySymbol.SetMethod.IsInitOnly)
|
||||
static bool PropertyIsExpressionBodiedAndReturnsNewCallable(Compilation compilation, IPropertySymbol? propertySymbol)
|
||||
{
|
||||
// This should never happen, as we filtered ReadOnly properties, but just in case.
|
||||
context.ReportDiagnostic(Diagnostic.Create(
|
||||
Common.ExportedMemberIsReadOnlyRule,
|
||||
propertySymbol.Locations.FirstLocationWithSourceTreeOrDefault(),
|
||||
propertySymbol.ToDisplayString()
|
||||
));
|
||||
return null;
|
||||
if (propertySymbol == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var propertyDeclarationSyntax = propertySymbol.DeclaringSyntaxReferences
|
||||
.Select(r => r.GetSyntax() as PropertyDeclarationSyntax).FirstOrDefault();
|
||||
if (propertyDeclarationSyntax == null || propertyDeclarationSyntax.Initializer != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (propertyDeclarationSyntax.AccessorList != null)
|
||||
{
|
||||
var accessors = propertyDeclarationSyntax.AccessorList.Accessors;
|
||||
foreach (var accessor in accessors)
|
||||
{
|
||||
if (!accessor.IsKind(SyntaxKind.GetAccessorDeclaration))
|
||||
{
|
||||
// Only getters are allowed.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ExpressionBodyReturnsNewCallable(compilation, accessor.ExpressionBody))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!ExpressionBodyReturnsNewCallable(compilation, propertyDeclarationSyntax.ExpressionBody))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ExpressionBodyReturnsNewCallable(Compilation compilation, ArrowExpressionClauseSyntax? expressionSyntax)
|
||||
{
|
||||
if (expressionSyntax == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var semanticModel = compilation.GetSemanticModel(expressionSyntax.SyntaxTree);
|
||||
|
||||
switch (expressionSyntax.Expression)
|
||||
{
|
||||
case ImplicitObjectCreationExpressionSyntax creationExpression:
|
||||
// We already validate that the property type must be 'Callable'
|
||||
// so we can assume this constructor is valid.
|
||||
return true;
|
||||
|
||||
case ObjectCreationExpressionSyntax creationExpression:
|
||||
var typeSymbol = semanticModel.GetSymbolInfo(creationExpression.Type).Symbol as ITypeSymbol;
|
||||
if (typeSymbol != null)
|
||||
{
|
||||
return typeSymbol.FullQualifiedNameOmitGlobal() == GodotClasses.Callable;
|
||||
}
|
||||
break;
|
||||
|
||||
case InvocationExpressionSyntax invocationExpression:
|
||||
var methodSymbol = semanticModel.GetSymbolInfo(invocationExpression).Symbol as IMethodSymbol;
|
||||
if (methodSymbol != null && methodSymbol.Name == "From")
|
||||
{
|
||||
return methodSymbol.ContainingType.FullQualifiedNameOmitGlobal() == GodotClasses.Callable;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -450,14 +559,41 @@ namespace Godot.SourceGenerators
|
|||
var memberVariantType = MarshalUtils.ConvertMarshalTypeToVariantType(marshalType)!.Value;
|
||||
string memberName = memberSymbol.Name;
|
||||
|
||||
string? hintString = null;
|
||||
|
||||
if (exportToolButtonAttr != null)
|
||||
{
|
||||
if (memberVariantType != VariantType.Callable)
|
||||
{
|
||||
context.ReportDiagnostic(Diagnostic.Create(
|
||||
Common.ExportToolButtonIsNotCallableRule,
|
||||
memberSymbol.Locations.FirstLocationWithSourceTreeOrDefault(),
|
||||
memberSymbol.ToDisplayString()
|
||||
));
|
||||
return null;
|
||||
}
|
||||
|
||||
hintString = exportToolButtonAttr.ConstructorArguments[0].Value?.ToString() ?? "";
|
||||
foreach (var namedArgument in exportToolButtonAttr.NamedArguments)
|
||||
{
|
||||
if (namedArgument is { Key: "Icon", Value.Value: string { Length: > 0 } })
|
||||
{
|
||||
hintString += $",{namedArgument.Value.Value}";
|
||||
}
|
||||
}
|
||||
|
||||
return new PropertyInfo(memberVariantType, memberName, PropertyHint.ToolButton,
|
||||
hintString: hintString, PropertyUsageFlags.Editor, exported: true);
|
||||
}
|
||||
|
||||
if (exportAttr == null)
|
||||
{
|
||||
return new PropertyInfo(memberVariantType, memberName, PropertyHint.None,
|
||||
hintString: null, PropertyUsageFlags.ScriptVariable, exported: false);
|
||||
hintString: hintString, PropertyUsageFlags.ScriptVariable, exported: false);
|
||||
}
|
||||
|
||||
if (!TryGetMemberExportHint(typeCache, memberType, exportAttr, memberVariantType,
|
||||
isTypeArgument: false, out var hint, out var hintString))
|
||||
isTypeArgument: false, out var hint, out hintString))
|
||||
{
|
||||
var constructorArguments = exportAttr.ConstructorArguments;
|
||||
|
||||
|
|
@ -728,8 +864,81 @@ namespace Godot.SourceGenerators
|
|||
|
||||
if (!isTypeArgument && variantType == VariantType.Dictionary)
|
||||
{
|
||||
// TODO: Dictionaries are not supported in the inspector
|
||||
return false;
|
||||
var elementTypes = MarshalUtils.GetGenericElementTypes(type);
|
||||
|
||||
if (elementTypes == null)
|
||||
return false; // Non-generic Dictionary, so there's no hint to add
|
||||
Debug.Assert(elementTypes.Length == 2);
|
||||
|
||||
var keyElementMarshalType = MarshalUtils.ConvertManagedTypeToMarshalType(elementTypes[0], typeCache);
|
||||
var valueElementMarshalType = MarshalUtils.ConvertManagedTypeToMarshalType(elementTypes[1], typeCache);
|
||||
|
||||
if (keyElementMarshalType == null || valueElementMarshalType == null)
|
||||
{
|
||||
// To maintain compatibility with previous versions of Godot before 4.4,
|
||||
// we must preserve the old behavior for generic dictionaries with non-marshallable
|
||||
// generic type arguments.
|
||||
return false;
|
||||
}
|
||||
|
||||
var keyElementVariantType = MarshalUtils.ConvertMarshalTypeToVariantType(keyElementMarshalType.Value)!.Value;
|
||||
var keyIsPresetHint = false;
|
||||
var keyHintString = (string?)null;
|
||||
|
||||
if (keyElementVariantType == VariantType.String || keyElementVariantType == VariantType.StringName)
|
||||
keyIsPresetHint = GetStringArrayEnumHint(keyElementVariantType, exportAttr, out keyHintString);
|
||||
|
||||
if (!keyIsPresetHint)
|
||||
{
|
||||
bool hintRes = TryGetMemberExportHint(typeCache, elementTypes[0],
|
||||
exportAttr, keyElementVariantType, isTypeArgument: true,
|
||||
out var keyElementHint, out var keyElementHintString);
|
||||
|
||||
// Format: type/hint:hint_string
|
||||
if (hintRes)
|
||||
{
|
||||
keyHintString = (int)keyElementVariantType + "/" + (int)keyElementHint + ":";
|
||||
|
||||
if (keyElementHintString != null)
|
||||
keyHintString += keyElementHintString;
|
||||
}
|
||||
else
|
||||
{
|
||||
keyHintString = (int)keyElementVariantType + "/" + (int)PropertyHint.None + ":";
|
||||
}
|
||||
}
|
||||
|
||||
var valueElementVariantType = MarshalUtils.ConvertMarshalTypeToVariantType(valueElementMarshalType.Value)!.Value;
|
||||
var valueIsPresetHint = false;
|
||||
var valueHintString = (string?)null;
|
||||
|
||||
if (valueElementVariantType == VariantType.String || valueElementVariantType == VariantType.StringName)
|
||||
valueIsPresetHint = GetStringArrayEnumHint(valueElementVariantType, exportAttr, out valueHintString);
|
||||
|
||||
if (!valueIsPresetHint)
|
||||
{
|
||||
bool hintRes = TryGetMemberExportHint(typeCache, elementTypes[1],
|
||||
exportAttr, valueElementVariantType, isTypeArgument: true,
|
||||
out var valueElementHint, out var valueElementHintString);
|
||||
|
||||
// Format: type/hint:hint_string
|
||||
if (hintRes)
|
||||
{
|
||||
valueHintString = (int)valueElementVariantType + "/" + (int)valueElementHint + ":";
|
||||
|
||||
if (valueElementHintString != null)
|
||||
valueHintString += valueElementHintString;
|
||||
}
|
||||
else
|
||||
{
|
||||
valueHintString = (int)valueElementVariantType + "/" + (int)PropertyHint.None + ":";
|
||||
}
|
||||
}
|
||||
|
||||
hint = PropertyHint.TypeString;
|
||||
|
||||
hintString = keyHintString != null && valueHintString != null ? $"{keyHintString};{valueHintString}" : null;
|
||||
return hintString != null;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -196,16 +196,13 @@ namespace Godot.SourceGenerators
|
|||
continue;
|
||||
}
|
||||
|
||||
if (marshalType == MarshalType.GodotObjectOrDerived)
|
||||
if (!isNode && MemberHasNodeType(propertyType, marshalType.Value))
|
||||
{
|
||||
if (!isNode && propertyType.InheritsFrom("GodotSharp", GodotClasses.Node))
|
||||
{
|
||||
context.ReportDiagnostic(Diagnostic.Create(
|
||||
Common.OnlyNodesShouldExportNodesRule,
|
||||
property.Locations.FirstLocationWithSourceTreeOrDefault()
|
||||
));
|
||||
continue;
|
||||
}
|
||||
context.ReportDiagnostic(Diagnostic.Create(
|
||||
Common.OnlyNodesShouldExportNodesRule,
|
||||
property.Locations.FirstLocationWithSourceTreeOrDefault()
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
||||
var propertyDeclarationSyntax = property.DeclaringSyntaxReferences
|
||||
|
|
@ -315,16 +312,13 @@ namespace Godot.SourceGenerators
|
|||
continue;
|
||||
}
|
||||
|
||||
if (marshalType == MarshalType.GodotObjectOrDerived)
|
||||
if (!isNode && MemberHasNodeType(fieldType, marshalType.Value))
|
||||
{
|
||||
if (!isNode && fieldType.InheritsFrom("GodotSharp", GodotClasses.Node))
|
||||
{
|
||||
context.ReportDiagnostic(Diagnostic.Create(
|
||||
Common.OnlyNodesShouldExportNodesRule,
|
||||
field.Locations.FirstLocationWithSourceTreeOrDefault()
|
||||
));
|
||||
continue;
|
||||
}
|
||||
context.ReportDiagnostic(Diagnostic.Create(
|
||||
Common.OnlyNodesShouldExportNodesRule,
|
||||
field.Locations.FirstLocationWithSourceTreeOrDefault()
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
||||
EqualsValueClauseSyntax? initializer = field.DeclaringSyntaxReferences
|
||||
|
|
@ -424,6 +418,27 @@ namespace Godot.SourceGenerators
|
|||
context.AddSource(uniqueHint, SourceText.From(source.ToString(), Encoding.UTF8));
|
||||
}
|
||||
|
||||
private static bool MemberHasNodeType(ITypeSymbol memberType, MarshalType marshalType)
|
||||
{
|
||||
if (marshalType == MarshalType.GodotObjectOrDerived)
|
||||
{
|
||||
return memberType.InheritsFrom("GodotSharp", GodotClasses.Node);
|
||||
}
|
||||
if (marshalType == MarshalType.GodotObjectOrDerivedArray)
|
||||
{
|
||||
var elementType = ((IArrayTypeSymbol)memberType).ElementType;
|
||||
return elementType.InheritsFrom("GodotSharp", GodotClasses.Node);
|
||||
}
|
||||
if (memberType is INamedTypeSymbol { IsGenericType: true } genericType)
|
||||
{
|
||||
return genericType.TypeArguments
|
||||
.Any(static typeArgument
|
||||
=> typeArgument.InheritsFrom("GodotSharp", GodotClasses.Node));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private struct ExportedPropertyMetadata
|
||||
{
|
||||
public ExportedPropertyMetadata(string name, MarshalType type, ITypeSymbol typeSymbol, string? value)
|
||||
|
|
|
|||
|
|
@ -5,13 +5,6 @@ using Microsoft.CodeAnalysis;
|
|||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Microsoft.CodeAnalysis.Text;
|
||||
|
||||
// TODO:
|
||||
// Determine a proper way to emit the signal.
|
||||
// 'Emit(nameof(TheEvent))' creates a StringName every time and has the overhead of string marshaling.
|
||||
// I haven't decided on the best option yet. Some possibilities:
|
||||
// - Expose the generated StringName fields to the user, for use with 'Emit(...)'.
|
||||
// - Generate a 'EmitSignalName' method for each event signal.
|
||||
|
||||
namespace Godot.SourceGenerators
|
||||
{
|
||||
[Generator]
|
||||
|
|
@ -276,7 +269,7 @@ namespace Godot.SourceGenerators
|
|||
source.Append(
|
||||
$" /// <inheritdoc cref=\"{signalDelegate.DelegateSymbol.FullQualifiedNameIncludeGlobal()}\"/>\n");
|
||||
|
||||
source.Append(" public event ")
|
||||
source.Append($" {signalDelegate.DelegateSymbol.GetAccessibilityKeyword()} event ")
|
||||
.Append(signalDelegate.DelegateSymbol.FullQualifiedNameIncludeGlobal())
|
||||
.Append(" @")
|
||||
.Append(signalName)
|
||||
|
|
@ -288,6 +281,43 @@ namespace Godot.SourceGenerators
|
|||
.Append(signalName)
|
||||
.Append(" -= value;\n")
|
||||
.Append("}\n");
|
||||
|
||||
// Generate EmitSignal{EventName} method to raise the event
|
||||
|
||||
var invokeMethodSymbol = signalDelegate.InvokeMethodData.Method;
|
||||
int paramCount = invokeMethodSymbol.Parameters.Length;
|
||||
|
||||
string raiseMethodModifiers = signalDelegate.DelegateSymbol.ContainingType.IsSealed ?
|
||||
"private" :
|
||||
"protected";
|
||||
|
||||
source.Append($" {raiseMethodModifiers} void EmitSignal{signalName}(");
|
||||
for (int i = 0; i < paramCount; i++)
|
||||
{
|
||||
var paramSymbol = invokeMethodSymbol.Parameters[i];
|
||||
source.Append($"{paramSymbol.Type.FullQualifiedNameIncludeGlobal()} @{paramSymbol.Name}");
|
||||
if (i < paramCount - 1)
|
||||
{
|
||||
source.Append(", ");
|
||||
}
|
||||
}
|
||||
source.Append(")\n");
|
||||
source.Append(" {\n");
|
||||
source.Append($" EmitSignal(SignalName.{signalName}");
|
||||
foreach (var paramSymbol in invokeMethodSymbol.Parameters)
|
||||
{
|
||||
// Enums must be converted to the underlying type before they can be implicitly converted to Variant
|
||||
if (paramSymbol.Type.TypeKind == TypeKind.Enum)
|
||||
{
|
||||
var underlyingType = ((INamedTypeSymbol)paramSymbol.Type).EnumUnderlyingType!;
|
||||
source.Append($", ({underlyingType.FullQualifiedNameIncludeGlobal()})@{paramSymbol.Name}");
|
||||
continue;
|
||||
}
|
||||
|
||||
source.Append($", @{paramSymbol.Name}");
|
||||
}
|
||||
source.Append(");\n");
|
||||
source.Append(" }\n");
|
||||
}
|
||||
|
||||
// Generate RaiseGodotClassSignalCallbacks
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ namespace GodotTools.BuildLogger
|
|||
|
||||
WriteLine(line);
|
||||
|
||||
string errorLine = $@"error,{e.File.CsvEscape()},{e.LineNumber},{e.ColumnNumber}," +
|
||||
string errorLine = $@"error,{e.File?.CsvEscape() ?? string.Empty},{e.LineNumber},{e.ColumnNumber}," +
|
||||
$"{e.Code?.CsvEscape() ?? string.Empty},{e.Message.CsvEscape()}," +
|
||||
$"{e.ProjectFile?.CsvEscape() ?? string.Empty}";
|
||||
_issuesStreamWriter.WriteLine(errorLine);
|
||||
|
|
@ -101,7 +101,7 @@ namespace GodotTools.BuildLogger
|
|||
|
||||
WriteLine(line);
|
||||
|
||||
string warningLine = $@"warning,{e.File.CsvEscape()},{e.LineNumber},{e.ColumnNumber}," +
|
||||
string warningLine = $@"warning,{e.File?.CsvEscape() ?? string.Empty},{e.LineNumber},{e.ColumnNumber}," +
|
||||
$"{e.Code?.CsvEscape() ?? string.Empty},{e.Message.CsvEscape()}," +
|
||||
$"{e.ProjectFile?.CsvEscape() ?? string.Empty}";
|
||||
_issuesStreamWriter.WriteLine(warningLine);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{639E48BD-44E5-4091-8EDD-22D36DC0768D}</ProjectGuid>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<LangVersion>10</LangVersion>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<LangVersion>10</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<RuntimeIdentifier>win-x86</RuntimeIdentifier>
|
||||
<SelfContained>False</SelfContained>
|
||||
<RollForward>LatestMajor</RollForward>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,22 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}</ProjectGuid>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<LangVersion>10</LangVersion>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Build" Version="15.1.548" ExcludeAssets="runtime" />
|
||||
<PackageReference Include="Microsoft.Build.Locator" Version="1.2.6" />
|
||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
|
||||
<PackageReference Include="NuGet.Frameworks" Version="6.12.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\GodotTools.Core\GodotTools.Core.csproj" />
|
||||
<ProjectReference Include="..\GodotTools.Shared\GodotTools.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ namespace GodotTools.ProjectEditor
|
|||
{
|
||||
public static string GodotSdkAttrValue => $"Godot.NET.Sdk/{GeneratedGodotNupkgsVersions.GodotNETSdk}";
|
||||
|
||||
public static string GodotMinimumRequiredTfm => "net8.0";
|
||||
|
||||
public static ProjectRootElement GenGameProject(string name)
|
||||
{
|
||||
if (name.Length == 0)
|
||||
|
|
@ -22,13 +24,7 @@ namespace GodotTools.ProjectEditor
|
|||
root.Sdk = GodotSdkAttrValue;
|
||||
|
||||
var mainGroup = root.AddPropertyGroup();
|
||||
mainGroup.AddProperty("TargetFramework", "net6.0");
|
||||
|
||||
var net7 = mainGroup.AddProperty("TargetFramework", "net7.0");
|
||||
net7.Condition = " '$(GodotTargetPlatform)' == 'android' ";
|
||||
|
||||
var net8 = mainGroup.AddProperty("TargetFramework", "net8.0");
|
||||
net8.Condition = " '$(GodotTargetPlatform)' == 'ios' ";
|
||||
mainGroup.AddProperty("TargetFramework", GodotMinimumRequiredTfm);
|
||||
|
||||
mainGroup.AddProperty("EnableDynamicLoading", "true");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Build.Construction;
|
||||
using Microsoft.Build.Evaluation;
|
||||
using Microsoft.Build.Locator;
|
||||
using NuGet.Frameworks;
|
||||
|
||||
namespace GodotTools.ProjectEditor
|
||||
{
|
||||
|
|
@ -19,8 +23,21 @@ namespace GodotTools.ProjectEditor
|
|||
}
|
||||
}
|
||||
|
||||
public static class ProjectUtils
|
||||
public static partial class ProjectUtils
|
||||
{
|
||||
[GeneratedRegex(@"\s*'\$\(GodotTargetPlatform\)'\s*==\s*'(?<platform>[A-z]+)'\s*", RegexOptions.IgnoreCase)]
|
||||
private static partial Regex GodotTargetPlatformConditionRegex();
|
||||
|
||||
private static readonly string[] _platformNames =
|
||||
{
|
||||
"windows",
|
||||
"linuxbsd",
|
||||
"macos",
|
||||
"android",
|
||||
"ios",
|
||||
"web",
|
||||
};
|
||||
|
||||
public static void MSBuildLocatorRegisterLatest(out Version version, out string path)
|
||||
{
|
||||
var instance = MSBuildLocator.QueryVisualStudioInstances()
|
||||
|
|
@ -36,11 +53,22 @@ namespace GodotTools.ProjectEditor
|
|||
|
||||
public static MSBuildProject? Open(string path)
|
||||
{
|
||||
var root = ProjectRootElement.Open(path);
|
||||
var root = ProjectRootElement.Open(path, ProjectCollection.GlobalProjectCollection, preserveFormatting: true);
|
||||
return root != null ? new MSBuildProject(root) : null;
|
||||
}
|
||||
|
||||
public static void MigrateToProjectSdksStyle(MSBuildProject project, string projectName)
|
||||
public static void UpgradeProjectIfNeeded(MSBuildProject project, string projectName)
|
||||
{
|
||||
// NOTE: The order in which changes are made to the project is important.
|
||||
|
||||
// Migrate to MSBuild project Sdks style if using the old style.
|
||||
MigrateToProjectSdksStyle(project, projectName);
|
||||
|
||||
EnsureGodotSdkIsUpToDate(project);
|
||||
EnsureTargetFrameworkMatchesMinimumRequirement(project);
|
||||
}
|
||||
|
||||
private static void MigrateToProjectSdksStyle(MSBuildProject project, string projectName)
|
||||
{
|
||||
var origRoot = project.Root;
|
||||
|
||||
|
|
@ -64,5 +92,128 @@ namespace GodotTools.ProjectEditor
|
|||
root.Sdk = godotSdkAttrValue;
|
||||
project.HasUnsavedChanges = true;
|
||||
}
|
||||
|
||||
private static void EnsureTargetFrameworkMatchesMinimumRequirement(MSBuildProject project)
|
||||
{
|
||||
var root = project.Root;
|
||||
string minTfmValue = ProjectGenerator.GodotMinimumRequiredTfm;
|
||||
var minTfmVersion = NuGetFramework.Parse(minTfmValue).Version;
|
||||
|
||||
ProjectPropertyGroupElement? mainPropertyGroup = null;
|
||||
ProjectPropertyElement? mainTargetFrameworkProperty = null;
|
||||
|
||||
var propertiesToChange = new List<ProjectPropertyElement>();
|
||||
|
||||
foreach (var propertyGroup in root.PropertyGroups)
|
||||
{
|
||||
bool groupHasCondition = !string.IsNullOrEmpty(propertyGroup.Condition);
|
||||
|
||||
// Check if the property group should be excluded from checking for 'TargetFramework' properties.
|
||||
if (groupHasCondition && !ConditionMatchesGodotPlatform(propertyGroup.Condition))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Store a reference to the first property group without conditions,
|
||||
// in case we need to add a new 'TargetFramework' property later.
|
||||
if (mainPropertyGroup == null && !groupHasCondition)
|
||||
{
|
||||
mainPropertyGroup = propertyGroup;
|
||||
}
|
||||
|
||||
foreach (var property in propertyGroup.Properties)
|
||||
{
|
||||
// We are looking for 'TargetFramework' properties.
|
||||
if (property.Name != "TargetFramework")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bool propertyHasCondition = !string.IsNullOrEmpty(property.Condition);
|
||||
|
||||
// Check if the property should be excluded.
|
||||
if (propertyHasCondition && !ConditionMatchesGodotPlatform(property.Condition))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!groupHasCondition && !propertyHasCondition)
|
||||
{
|
||||
// Store a reference to the 'TargetFramework' that has no conditions
|
||||
// because it applies to all platforms.
|
||||
if (mainTargetFrameworkProperty == null)
|
||||
{
|
||||
mainTargetFrameworkProperty = property;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the 'TargetFramework' property is conditional, it may no longer be needed
|
||||
// when the main one is upgraded to the new minimum version.
|
||||
var tfmVersion = NuGetFramework.Parse(property.Value).Version;
|
||||
if (tfmVersion <= minTfmVersion)
|
||||
{
|
||||
propertiesToChange.Add(property);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mainTargetFrameworkProperty == null)
|
||||
{
|
||||
// We haven't found a 'TargetFramework' property without conditions,
|
||||
// we'll just add one in the first property group without conditions.
|
||||
if (mainPropertyGroup == null)
|
||||
{
|
||||
// We also don't have a property group without conditions,
|
||||
// so we'll add a new one to the project.
|
||||
mainPropertyGroup = root.AddPropertyGroup();
|
||||
}
|
||||
|
||||
mainTargetFrameworkProperty = mainPropertyGroup.AddProperty("TargetFramework", minTfmValue);
|
||||
project.HasUnsavedChanges = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var tfmVersion = NuGetFramework.Parse(mainTargetFrameworkProperty.Value).Version;
|
||||
if (tfmVersion < minTfmVersion)
|
||||
{
|
||||
mainTargetFrameworkProperty.Value = minTfmValue;
|
||||
project.HasUnsavedChanges = true;
|
||||
}
|
||||
}
|
||||
|
||||
var mainTfmVersion = NuGetFramework.Parse(mainTargetFrameworkProperty.Value).Version;
|
||||
foreach (var property in propertiesToChange)
|
||||
{
|
||||
// If the main 'TargetFramework' property targets a version newer than
|
||||
// the minimum required by Godot, we don't want to remove the conditional
|
||||
// 'TargetFramework' properties, only upgrade them to the new minimum.
|
||||
// Otherwise, it can be removed.
|
||||
if (mainTfmVersion > minTfmVersion)
|
||||
{
|
||||
property.Value = minTfmValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
property.Parent.RemoveChild(property);
|
||||
}
|
||||
|
||||
project.HasUnsavedChanges = true;
|
||||
}
|
||||
|
||||
static bool ConditionMatchesGodotPlatform(string condition)
|
||||
{
|
||||
// Check if the condition is checking the 'GodotTargetPlatform' for one of the
|
||||
// Godot platforms with built-in support in the Godot.NET.Sdk.
|
||||
var match = GodotTargetPlatformConditionRegex().Match(condition);
|
||||
if (match.Success)
|
||||
{
|
||||
string platform = match.Groups["platform"].Value;
|
||||
return _platformNames.Contains(platform, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<!-- Specify compile items manually to avoid including dangling generated items. -->
|
||||
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
|
||||
</PropertyGroup>
|
||||
<Import Project="GenerateGodotNupkgsVersions.targets" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
<!-- Specify compile items manually to avoid including dangling generated items. -->
|
||||
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="GenerateGodotNupkgsVersions.targets" />
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -265,11 +265,6 @@ namespace GodotTools.Build
|
|||
success = Publish(buildInfo);
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
ShowBuildErrorDialog("Failed to publish .NET project");
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,19 @@ namespace GodotTools.Export
|
|||
};
|
||||
}
|
||||
|
||||
private string? _maybeLastExportError;
|
||||
private void AddExceptionMessage(EditorExportPlatform platform, Exception exception)
|
||||
{
|
||||
string? exceptionMessage = exception.Message;
|
||||
if (string.IsNullOrEmpty(exceptionMessage))
|
||||
{
|
||||
exceptionMessage = $"Exception thrown: {exception.GetType().Name}";
|
||||
}
|
||||
|
||||
platform.AddMessage(EditorExportPlatform.ExportMessageType.Error, "Export .NET Project", exceptionMessage);
|
||||
|
||||
// We also print exceptions as we receive them to stderr.
|
||||
Console.Error.WriteLine(exception);
|
||||
}
|
||||
|
||||
// With this method we can override how a file is exported in the PCK
|
||||
public override void _ExportFile(string path, string type, string[] features)
|
||||
|
|
@ -92,8 +104,8 @@ namespace GodotTools.Export
|
|||
|
||||
if (!ProjectContainsDotNet())
|
||||
{
|
||||
_maybeLastExportError = $"This project contains C# files but no solution file was found at the following path: {GodotSharpDirs.ProjectSlnPath}\n" +
|
||||
"A solution file is required for projects with C# files. Please ensure that the solution file exists in the specified location and try again.";
|
||||
GetExportPlatform().AddMessage(EditorExportPlatform.ExportMessageType.Error, "Export .NET Project", $"This project contains C# files but no solution file was found at the following path: {GodotSharpDirs.ProjectSlnPath}\n" +
|
||||
"A solution file is required for projects with C# files. Please ensure that the solution file exists in the specified location and try again.");
|
||||
throw new InvalidOperationException($"{path} is a C# file but no solution file exists.");
|
||||
}
|
||||
|
||||
|
|
@ -124,16 +136,7 @@ namespace GodotTools.Export
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_maybeLastExportError = e.Message;
|
||||
|
||||
// 'maybeLastExportError' cannot be null or empty if there was an error, so we
|
||||
// must consider the possibility of exceptions being thrown without a message.
|
||||
if (string.IsNullOrEmpty(_maybeLastExportError))
|
||||
_maybeLastExportError = $"Exception thrown: {e.GetType().Name}";
|
||||
|
||||
GD.PushError($"Failed to export project: {_maybeLastExportError}");
|
||||
Console.Error.WriteLine(e);
|
||||
// TODO: Do something on error once _ExportBegin supports failing.
|
||||
AddExceptionMessage(GetExportPlatform(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -144,7 +147,9 @@ namespace GodotTools.Export
|
|||
if (!ProjectContainsDotNet())
|
||||
return;
|
||||
|
||||
if (!DeterminePlatformFromFeatures(features, out string? platform))
|
||||
string osName = GetExportPlatform().GetOsName();
|
||||
|
||||
if (!TryDeterminePlatformFromOSName(osName, out string? platform))
|
||||
throw new NotSupportedException("Target platform not supported.");
|
||||
|
||||
if (!new[] { OS.Platforms.Windows, OS.Platforms.LinuxBSD, OS.Platforms.MacOS, OS.Platforms.Android, OS.Platforms.iOS }
|
||||
|
|
@ -211,6 +216,8 @@ namespace GodotTools.Export
|
|||
|
||||
bool embedBuildResults = ((bool)GetOption("dotnet/embed_build_outputs") || platform == OS.Platforms.Android) && platform != OS.Platforms.MacOS;
|
||||
|
||||
var exportedJars = new HashSet<string>();
|
||||
|
||||
foreach (PublishConfig config in targets)
|
||||
{
|
||||
string ridOS = config.RidOS;
|
||||
|
|
@ -240,7 +247,6 @@ namespace GodotTools.Export
|
|||
{
|
||||
publishOutputDir = Path.Combine(GodotSharpDirs.ProjectBaseOutputPath, "godot-publish-dotnet",
|
||||
$"{buildConfig}-{runtimeIdentifier}");
|
||||
|
||||
}
|
||||
|
||||
outputPaths.Add(publishOutputDir);
|
||||
|
|
@ -317,6 +323,41 @@ namespace GodotTools.Export
|
|||
{
|
||||
if (embedBuildResults)
|
||||
{
|
||||
if (platform == OS.Platforms.Android)
|
||||
{
|
||||
string fileName = Path.GetFileName(path);
|
||||
|
||||
if (IsSharedObject(fileName))
|
||||
{
|
||||
AddSharedObject(path, tags: new string[] { arch },
|
||||
Path.Join(projectDataDirName,
|
||||
Path.GetRelativePath(publishOutputDir,
|
||||
Path.GetDirectoryName(path)!)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool IsSharedObject(string fileName)
|
||||
{
|
||||
if (fileName.EndsWith(".jar"))
|
||||
{
|
||||
// Don't export the same jar twice. Otherwise we will have conflicts.
|
||||
// This can happen when exporting for multiple architectures. Dotnet
|
||||
// stores the jars in .godot/mono/temp/bin/Export[Debug|Release] per
|
||||
// target architecture. Jars are cpu agnostic so only 1 is needed.
|
||||
var jarName = Path.GetFileName(fileName);
|
||||
return exportedJars.Add(jarName);
|
||||
}
|
||||
|
||||
if (fileName.EndsWith(".so") || fileName.EndsWith(".a") || fileName.EndsWith(".dex"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
string filePath = SanitizeSlashes(Path.GetRelativePath(publishOutputDir, path));
|
||||
byte[] fileData = File.ReadAllBytes(path);
|
||||
string hash = Convert.ToBase64String(SHA512.HashData(fileData));
|
||||
|
|
@ -355,24 +396,23 @@ namespace GodotTools.Export
|
|||
if (outputPaths.Count > 2)
|
||||
{
|
||||
// lipo the simulator binaries together
|
||||
// TODO: Move this to the native lipo implementation we have in the macos export plugin.
|
||||
var lipoArgs = new List<string>();
|
||||
lipoArgs.Add("-create");
|
||||
lipoArgs.AddRange(outputPaths.Skip(1).Select(x => Path.Combine(x, $"{GodotSharpDirs.ProjectAssemblyName}.dylib")));
|
||||
lipoArgs.Add("-output");
|
||||
lipoArgs.Add(Path.Combine(outputPaths[1], $"{GodotSharpDirs.ProjectAssemblyName}.dylib"));
|
||||
|
||||
int lipoExitCode = OS.ExecuteCommand(XcodeHelper.FindXcodeTool("lipo"), lipoArgs);
|
||||
if (lipoExitCode != 0)
|
||||
throw new InvalidOperationException($"Command 'lipo' exited with code: {lipoExitCode}.");
|
||||
string outputPath = Path.Combine(outputPaths[1], $"{GodotSharpDirs.ProjectAssemblyName}.dylib");
|
||||
string[] files = outputPaths
|
||||
.Skip(1)
|
||||
.Select(path => Path.Combine(path, $"{GodotSharpDirs.ProjectAssemblyName}.dylib"))
|
||||
.ToArray();
|
||||
|
||||
if (!Internal.LipOCreateFile(outputPath, files))
|
||||
{
|
||||
throw new InvalidOperationException($"Failed to 'lipo' simulator binaries.");
|
||||
}
|
||||
|
||||
outputPaths.RemoveRange(2, outputPaths.Count - 2);
|
||||
}
|
||||
|
||||
var xcFrameworkPath = Path.Combine(GodotSharpDirs.ProjectBaseOutputPath, publishConfig.BuildConfig,
|
||||
$"{GodotSharpDirs.ProjectAssemblyName}_aot.xcframework");
|
||||
if (!BuildManager.GenerateXCFrameworkBlocking(outputPaths,
|
||||
Path.Combine(GodotSharpDirs.ProjectBaseOutputPath, publishConfig.BuildConfig, xcFrameworkPath)))
|
||||
string xcFrameworkPath = Path.Combine(GodotSharpDirs.ProjectBaseOutputPath, publishConfig.BuildConfig, $"{GodotSharpDirs.ProjectAssemblyName}_aot.xcframework");
|
||||
if (!BuildManager.GenerateXCFrameworkBlocking(outputPaths, xcFrameworkPath))
|
||||
{
|
||||
throw new InvalidOperationException("Failed to generate xcframework.");
|
||||
}
|
||||
|
|
@ -446,25 +486,22 @@ namespace GodotTools.Export
|
|||
Directory.Delete(folder, recursive: true);
|
||||
}
|
||||
_tempFolders.Clear();
|
||||
|
||||
// TODO: The following is just a workaround until the export plugins can be made to abort with errors
|
||||
|
||||
// We check for empty as well, because it's set to empty after hot-reloading
|
||||
if (!string.IsNullOrEmpty(_maybeLastExportError))
|
||||
{
|
||||
string lastExportError = _maybeLastExportError;
|
||||
_maybeLastExportError = null;
|
||||
|
||||
GodotSharpEditor.Instance.ShowErrorDialog(lastExportError, "Failed to export C# project");
|
||||
}
|
||||
}
|
||||
|
||||
private static bool DeterminePlatformFromFeatures(IEnumerable<string> features, [NotNullWhen(true)] out string? platform)
|
||||
/// <summary>
|
||||
/// Tries to determine the platform from the export preset's platform OS name.
|
||||
/// </summary>
|
||||
/// <param name="osName">Name of the export operating system.</param>
|
||||
/// <param name="platform">Platform name for the recognized supported platform.</param>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> when the platform OS name is recognized as a supported platform,
|
||||
/// <see langword="false"/> otherwise.
|
||||
/// </returns>
|
||||
private static bool TryDeterminePlatformFromOSName(string osName, [NotNullWhen(true)] out string? platform)
|
||||
{
|
||||
foreach (var feature in features)
|
||||
if (OS.PlatformFeatureMap.TryGetValue(osName, out platform))
|
||||
{
|
||||
if (OS.PlatformFeatureMap.TryGetValue(feature, out platform))
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
platform = null;
|
||||
|
|
|
|||
|
|
@ -1,93 +0,0 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace GodotTools.Export
|
||||
{
|
||||
public static class XcodeHelper
|
||||
{
|
||||
private static string? _XcodePath = null;
|
||||
|
||||
public static string XcodePath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_XcodePath == null)
|
||||
{
|
||||
_XcodePath = FindXcode();
|
||||
|
||||
if (_XcodePath == null)
|
||||
throw new FileNotFoundException("Could not find Xcode.");
|
||||
}
|
||||
|
||||
return _XcodePath;
|
||||
}
|
||||
}
|
||||
|
||||
private static string? FindSelectedXcode()
|
||||
{
|
||||
var outputWrapper = new Godot.Collections.Array();
|
||||
|
||||
int exitCode = Godot.OS.Execute("xcode-select", new string[] { "--print-path" }, output: outputWrapper);
|
||||
|
||||
if (exitCode == 0)
|
||||
{
|
||||
string output = (string)outputWrapper[0];
|
||||
return output.Trim();
|
||||
}
|
||||
|
||||
Console.Error.WriteLine($"'xcode-select --print-path' exited with code: {exitCode}");
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string? FindXcode()
|
||||
{
|
||||
string? selectedXcode = FindSelectedXcode();
|
||||
if (selectedXcode != null)
|
||||
{
|
||||
if (Directory.Exists(Path.Combine(selectedXcode, "Contents", "Developer")))
|
||||
return selectedXcode;
|
||||
|
||||
// The path already pointed to Contents/Developer
|
||||
var dirInfo = new DirectoryInfo(selectedXcode);
|
||||
if (dirInfo is not { Parent.Name: "Contents", Name: "Developer" })
|
||||
{
|
||||
Console.WriteLine(Path.GetDirectoryName(selectedXcode));
|
||||
Console.WriteLine(System.IO.Directory.GetParent(selectedXcode)?.Name);
|
||||
Console.Error.WriteLine("Unrecognized path for selected Xcode");
|
||||
}
|
||||
else
|
||||
{
|
||||
return System.IO.Path.GetFullPath($"{selectedXcode}/../..");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Error.WriteLine("Could not find the selected Xcode; trying with a hint path");
|
||||
}
|
||||
|
||||
const string XcodeHintPath = "/Applications/Xcode.app";
|
||||
|
||||
if (Directory.Exists(XcodeHintPath))
|
||||
{
|
||||
if (Directory.Exists(Path.Combine(XcodeHintPath, "Contents", "Developer")))
|
||||
return XcodeHintPath;
|
||||
|
||||
Console.Error.WriteLine($"Found Xcode at '{XcodeHintPath}' but it's missing the 'Contents/Developer' sub-directory");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string FindXcodeTool(string toolName)
|
||||
{
|
||||
string XcodeDefaultToolchain = Path.Combine(XcodePath, "Contents", "Developer", "Toolchains", "XcodeDefault.xctoolchain");
|
||||
|
||||
string path = Path.Combine(XcodeDefaultToolchain, "usr", "bin", toolName);
|
||||
if (File.Exists(path))
|
||||
return path;
|
||||
|
||||
throw new FileNotFoundException($"Cannot find Xcode tool: {toolName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ using System.Collections.Generic;
|
|||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using GodotTools.Build;
|
||||
using GodotTools.Ides;
|
||||
using GodotTools.Ides.Rider;
|
||||
|
|
@ -176,7 +177,7 @@ namespace GodotTools
|
|||
|
||||
private static readonly string[] VsCodeNames =
|
||||
{
|
||||
"code", "code-oss", "vscode", "vscode-oss", "visual-studio-code", "visual-studio-code-oss"
|
||||
"code", "code-oss", "vscode", "vscode-oss", "visual-studio-code", "visual-studio-code-oss", "codium"
|
||||
};
|
||||
|
||||
[UsedImplicitly]
|
||||
|
|
@ -259,11 +260,12 @@ namespace GodotTools
|
|||
|
||||
var args = new List<string>
|
||||
{
|
||||
Path.Combine(GodotSharpDirs.DataEditorToolsDir, "GodotTools.OpenVisualStudio.dll"),
|
||||
GodotSharpDirs.ProjectSlnPath,
|
||||
line >= 0 ? $"{scriptPath};{line + 1};{col + 1}" : scriptPath
|
||||
};
|
||||
|
||||
string command = Path.Combine(GodotSharpDirs.DataEditorToolsDir, "GodotTools.OpenVisualStudio.exe");
|
||||
string command = DotNetFinder.FindDotNetExe() ?? "dotnet";
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -328,7 +330,7 @@ namespace GodotTools
|
|||
args.Add("-b");
|
||||
args.Add(vscodeBundleId);
|
||||
|
||||
// The reusing of existing windows made by the 'open' command might not choose a wubdiw that is
|
||||
// The reusing of existing windows made by the 'open' command might not choose a window that is
|
||||
// editing our folder. It's better to ask for a new window and let VSCode do the window management.
|
||||
args.Add("-n");
|
||||
|
||||
|
|
@ -337,6 +339,28 @@ namespace GodotTools
|
|||
|
||||
args.Add("--args");
|
||||
}
|
||||
|
||||
// Try VSCodium as a fallback if Visual Studio Code can't be found.
|
||||
if (!macOSAppBundleInstalled)
|
||||
{
|
||||
const string VscodiumBundleId = "com.vscodium.codium";
|
||||
macOSAppBundleInstalled = Internal.IsMacOSAppBundleInstalled(VscodiumBundleId);
|
||||
|
||||
if (macOSAppBundleInstalled)
|
||||
{
|
||||
args.Add("-b");
|
||||
args.Add(VscodiumBundleId);
|
||||
|
||||
// The reusing of existing windows made by the 'open' command might not choose a window that is
|
||||
// editing our folder. It's better to ask for a new window and let VSCode do the window management.
|
||||
args.Add("-n");
|
||||
|
||||
// The open process must wait until the application finishes (which is instant in VSCode's case)
|
||||
args.Add("--wait-apps");
|
||||
|
||||
args.Add("--args");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
args.Add(Path.GetDirectoryName(GodotSharpDirs.ProjectSlnPath)!);
|
||||
|
|
@ -359,7 +383,7 @@ namespace GodotTools
|
|||
{
|
||||
if (!macOSAppBundleInstalled && string.IsNullOrEmpty(_vsCodePath))
|
||||
{
|
||||
GD.PushError("Cannot find code editor: VSCode");
|
||||
GD.PushError("Cannot find code editor: Visual Studio Code or VSCodium");
|
||||
return Error.FileNotFound;
|
||||
}
|
||||
|
||||
|
|
@ -369,7 +393,7 @@ namespace GodotTools
|
|||
{
|
||||
if (string.IsNullOrEmpty(_vsCodePath))
|
||||
{
|
||||
GD.PushError("Cannot find code editor: VSCode");
|
||||
GD.PushError("Cannot find code editor: Visual Studio Code or VSCodium");
|
||||
return Error.FileNotFound;
|
||||
}
|
||||
|
||||
|
|
@ -382,7 +406,7 @@ namespace GodotTools
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
GD.PushError($"Error when trying to run code editor: VSCode. Exception message: '{e.Message}'");
|
||||
GD.PushError($"Error when trying to run code editor: Visual Studio Code or VSCodium. Exception message: '{e.Message}'");
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
@ -415,12 +439,7 @@ namespace GodotTools
|
|||
var msbuildProject = ProjectUtils.Open(GodotSharpDirs.ProjectCsProjPath)
|
||||
?? throw new InvalidOperationException("Cannot open C# project.");
|
||||
|
||||
// NOTE: The order in which changes are made to the project is important
|
||||
|
||||
// Migrate to MSBuild project Sdks style if using the old style
|
||||
ProjectUtils.MigrateToProjectSdksStyle(msbuildProject, GodotSharpDirs.ProjectAssemblyName);
|
||||
|
||||
ProjectUtils.EnsureGodotSdkIsUpToDate(msbuildProject);
|
||||
ProjectUtils.UpgradeProjectIfNeeded(msbuildProject, GodotSharpDirs.ProjectAssemblyName);
|
||||
|
||||
if (msbuildProject.HasUnsavedChanges)
|
||||
{
|
||||
|
|
@ -548,7 +567,7 @@ namespace GodotTools
|
|||
{
|
||||
settingsHintStr += $",Visual Studio:{(int)ExternalEditorId.VisualStudio}" +
|
||||
$",MonoDevelop:{(int)ExternalEditorId.MonoDevelop}" +
|
||||
$",Visual Studio Code:{(int)ExternalEditorId.VsCode}" +
|
||||
$",Visual Studio Code and VSCodium:{(int)ExternalEditorId.VsCode}" +
|
||||
$",JetBrains Rider and Fleet:{(int)ExternalEditorId.Rider}" +
|
||||
$",Custom:{(int)ExternalEditorId.CustomEditor}";
|
||||
}
|
||||
|
|
@ -556,14 +575,14 @@ namespace GodotTools
|
|||
{
|
||||
settingsHintStr += $",Visual Studio:{(int)ExternalEditorId.VisualStudioForMac}" +
|
||||
$",MonoDevelop:{(int)ExternalEditorId.MonoDevelop}" +
|
||||
$",Visual Studio Code:{(int)ExternalEditorId.VsCode}" +
|
||||
$",Visual Studio Code and VSCodium:{(int)ExternalEditorId.VsCode}" +
|
||||
$",JetBrains Rider and Fleet:{(int)ExternalEditorId.Rider}" +
|
||||
$",Custom:{(int)ExternalEditorId.CustomEditor}";
|
||||
}
|
||||
else if (OS.IsUnixLike)
|
||||
{
|
||||
settingsHintStr += $",MonoDevelop:{(int)ExternalEditorId.MonoDevelop}" +
|
||||
$",Visual Studio Code:{(int)ExternalEditorId.VsCode}" +
|
||||
$",Visual Studio Code and VSCodium:{(int)ExternalEditorId.VsCode}" +
|
||||
$",JetBrains Rider and Fleet:{(int)ExternalEditorId.Rider}" +
|
||||
$",Custom:{(int)ExternalEditorId.CustomEditor}";
|
||||
}
|
||||
|
|
@ -700,6 +719,23 @@ namespace GodotTools
|
|||
private static IntPtr InternalCreateInstance(IntPtr unmanagedCallbacks, int unmanagedCallbacksSize)
|
||||
{
|
||||
Internal.Initialize(unmanagedCallbacks, unmanagedCallbacksSize);
|
||||
|
||||
var populateConstructorMethod =
|
||||
AppDomain.CurrentDomain
|
||||
.GetAssemblies()
|
||||
.First(x => x.GetName().Name == "GodotSharpEditor")
|
||||
.GetType("Godot.EditorConstructors")?
|
||||
.GetMethod("AddEditorConstructors",
|
||||
BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
|
||||
if (populateConstructorMethod == null)
|
||||
{
|
||||
throw new MissingMethodException("Godot.EditorConstructors",
|
||||
"AddEditorConstructors");
|
||||
}
|
||||
|
||||
populateConstructorMethod.Invoke(null, null);
|
||||
|
||||
return new GodotSharpEditor().NativeInstance;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{27B00618-A6F2-4828-B922-05CAEB08C286}</ProjectGuid>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
<EnableDynamicLoading>true</EnableDynamicLoading>
|
||||
<LangVersion>10</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<!-- The Godot editor uses the Debug Godot API assemblies -->
|
||||
<GodotApiConfiguration>Debug</GodotApiConfiguration>
|
||||
|
|
@ -13,13 +14,16 @@
|
|||
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Needed for our source generators to work despite this not being a Godot game project -->
|
||||
<PropertyGroup>
|
||||
<IsGodotToolsProject>true</IsGodotToolsProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<CompilerVisibleProperty Include="IsGodotToolsProject" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Condition=" Exists('$(GodotApiAssembliesDir)/GodotSharp.dll') ">
|
||||
<!-- The project is part of the Godot source tree -->
|
||||
<!-- Use the Godot source tree output folder instead of '$(ProjectDir)/bin' -->
|
||||
|
|
@ -27,6 +31,7 @@
|
|||
<!-- Must not append '$(TargetFramework)' to the output path in this case -->
|
||||
<AppendTargetFrameworkToOutputPath>False</AppendTargetFrameworkToOutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2019.1.3.0" ExcludeAssets="runtime" PrivateAssets="all" />
|
||||
<PackageReference Include="JetBrains.Rider.PathLocator" Version="1.0.9" />
|
||||
|
|
@ -41,14 +46,17 @@
|
|||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Godot.NET.Sdk\Godot.SourceGenerators\Godot.SourceGenerators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
||||
<ProjectReference Include="..\..\..\glue\GodotSharp\Godot.SourceGenerators.Internal\Godot.SourceGenerators.Internal.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\GodotTools.BuildLogger\GodotTools.BuildLogger.csproj" />
|
||||
<ProjectReference Include="..\GodotTools.IdeMessaging\GodotTools.IdeMessaging.csproj" />
|
||||
<ProjectReference Include="..\GodotTools.ProjectEditor\GodotTools.ProjectEditor.csproj" />
|
||||
<ProjectReference Include="..\GodotTools.Core\GodotTools.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -35,6 +35,13 @@ namespace GodotTools.Internals
|
|||
return godot_icall_Internal_IsMacOSAppBundleInstalled(bundleIdIn);
|
||||
}
|
||||
|
||||
public static bool LipOCreateFile(string outputPath, string[] files)
|
||||
{
|
||||
using godot_string outputPathIn = Marshaling.ConvertStringToNative(outputPath);
|
||||
using godot_packed_string_array filesIn = Marshaling.ConvertSystemArrayToNativePackedStringArray(files);
|
||||
return godot_icall_Internal_LipOCreateFile(outputPathIn, filesIn);
|
||||
}
|
||||
|
||||
public static bool GodotIs32Bits() => godot_icall_Internal_GodotIs32Bits();
|
||||
|
||||
public static bool GodotIsRealTDouble() => godot_icall_Internal_GodotIsRealTDouble();
|
||||
|
|
@ -121,6 +128,8 @@ namespace GodotTools.Internals
|
|||
|
||||
private static partial bool godot_icall_Internal_IsMacOSAppBundleInstalled(in godot_string bundleId);
|
||||
|
||||
private static partial bool godot_icall_Internal_LipOCreateFile(in godot_string outputPath, in godot_packed_string_array files);
|
||||
|
||||
private static partial bool godot_icall_Internal_GodotIs32Bits();
|
||||
|
||||
private static partial bool godot_icall_Internal_GodotIsRealTDouble();
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -265,6 +265,7 @@ class BindingsGenerator {
|
|||
bool is_singleton = false;
|
||||
bool is_singleton_instance = false;
|
||||
bool is_ref_counted = false;
|
||||
bool is_span_compatible = false;
|
||||
|
||||
/**
|
||||
* Class is a singleton, but can't be declared as a static class as that would
|
||||
|
|
@ -803,15 +804,17 @@ class BindingsGenerator {
|
|||
void _append_text_param(StringBuilder &p_output, const String &p_link_target);
|
||||
void _append_text_undeclared(StringBuilder &p_output, const String &p_link_target);
|
||||
|
||||
void _append_xml_method(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts);
|
||||
void _append_xml_member(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts);
|
||||
void _append_xml_signal(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts);
|
||||
void _append_xml_enum(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts);
|
||||
void _append_xml_method(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts, const TypeInterface *p_source_itype);
|
||||
void _append_xml_member(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts, const TypeInterface *p_source_itype);
|
||||
void _append_xml_signal(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts, const TypeInterface *p_source_itype);
|
||||
void _append_xml_enum(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts, const TypeInterface *p_source_itype);
|
||||
void _append_xml_constant(StringBuilder &p_xml_output, const TypeInterface *p_target_itype, const StringName &p_target_cname, const String &p_link_target, const Vector<String> &p_link_target_parts);
|
||||
void _append_xml_constant_in_global_scope(StringBuilder &p_xml_output, const String &p_target_cname, const String &p_link_target);
|
||||
void _append_xml_param(StringBuilder &p_xml_output, const String &p_link_target, bool p_is_signal);
|
||||
void _append_xml_undeclared(StringBuilder &p_xml_output, const String &p_link_target);
|
||||
|
||||
bool _validate_api_type(const TypeInterface *p_target_itype, const TypeInterface *p_source_itype);
|
||||
|
||||
int _determine_enum_prefix(const EnumInterface &p_ienum);
|
||||
void _apply_prefix_to_enum_constants(EnumInterface &p_ienum, int p_prefix_length);
|
||||
|
||||
|
|
@ -840,7 +843,7 @@ class BindingsGenerator {
|
|||
Error _generate_cs_type(const TypeInterface &itype, const String &p_output_file);
|
||||
|
||||
Error _generate_cs_property(const TypeInterface &p_itype, const PropertyInterface &p_iprop, StringBuilder &p_output);
|
||||
Error _generate_cs_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output);
|
||||
Error _generate_cs_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output, bool p_use_span);
|
||||
Error _generate_cs_signal(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::SignalInterface &p_isignal, StringBuilder &p_output);
|
||||
|
||||
Error _generate_cs_native_calls(const InternalCall &p_icall, StringBuilder &r_output);
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
|
|||
continue;
|
||||
}
|
||||
|
||||
String name = prop.name.substr(prop.name.find("/") + 1, prop.name.length());
|
||||
String name = prop.name.substr(prop.name.find_char('/') + 1, prop.name.length());
|
||||
suggestions.push_back(quoted(name));
|
||||
}
|
||||
} break;
|
||||
|
|
|
|||
|
|
@ -41,9 +41,11 @@
|
|||
#include "core/os/os.h"
|
||||
#include "core/version.h"
|
||||
#include "editor/debugger/editor_debugger_node.h"
|
||||
#include "editor/editor_main_screen.h"
|
||||
#include "editor/editor_node.h"
|
||||
#include "editor/editor_paths.h"
|
||||
#include "editor/editor_settings.h"
|
||||
#include "editor/export/lipo.h"
|
||||
#include "editor/gui/editor_run_bar.h"
|
||||
#include "editor/plugins/script_editor_plugin.h"
|
||||
#include "editor/themes/editor_scale.h"
|
||||
|
|
@ -117,6 +119,13 @@ bool godot_icall_Internal_IsMacOSAppBundleInstalled(const godot_string *p_bundle
|
|||
#endif
|
||||
}
|
||||
|
||||
bool godot_icall_Internal_LipOCreateFile(const godot_string *p_output_path, const godot_packed_array *p_files) {
|
||||
String output_path = *reinterpret_cast<const String *>(p_output_path);
|
||||
PackedStringArray files = *reinterpret_cast<const PackedStringArray *>(p_files);
|
||||
LipO lip;
|
||||
return lip.create_file(output_path, files);
|
||||
}
|
||||
|
||||
bool godot_icall_Internal_GodotIs32Bits() {
|
||||
return sizeof(void *) == 4;
|
||||
}
|
||||
|
|
@ -157,7 +166,7 @@ bool godot_icall_Internal_ScriptEditorEdit(Resource *p_resource, int32_t p_line,
|
|||
}
|
||||
|
||||
void godot_icall_Internal_EditorNodeShowScriptScreen() {
|
||||
EditorNode::get_singleton()->editor_select(EditorNode::EDITOR_SCRIPT);
|
||||
EditorNode::get_editor_main_screen()->select(EditorMainScreen::EDITOR_SCRIPT);
|
||||
}
|
||||
|
||||
void godot_icall_Internal_EditorRunPlay() {
|
||||
|
|
@ -258,6 +267,7 @@ static const void *unmanaged_callbacks[]{
|
|||
(void *)godot_icall_EditorProgress_Step,
|
||||
(void *)godot_icall_Internal_FullExportTemplatesDir,
|
||||
(void *)godot_icall_Internal_IsMacOSAppBundleInstalled,
|
||||
(void *)godot_icall_Internal_LipOCreateFile,
|
||||
(void *)godot_icall_Internal_GodotIs32Bits,
|
||||
(void *)godot_icall_Internal_GodotIsRealTDouble,
|
||||
(void *)godot_icall_Internal_GodotMainIteration,
|
||||
|
|
|
|||
|
|
@ -216,6 +216,7 @@ bool get_default_installation_dir(String &r_dotnet_root) {
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifndef WINDOWS_ENABLED
|
||||
bool get_install_location_from_file(const String &p_file_path, String &r_dotnet_root) {
|
||||
Error err = OK;
|
||||
Ref<FileAccess> f = FileAccess::open(p_file_path, FileAccess::READ, &err);
|
||||
|
|
@ -233,6 +234,7 @@ bool get_install_location_from_file(const String &p_file_path, String &r_dotnet_
|
|||
r_dotnet_root = line;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool get_dotnet_self_registered_dir(String &r_dotnet_root) {
|
||||
#if defined(WINDOWS_ENABLED)
|
||||
|
|
@ -260,7 +262,7 @@ bool get_dotnet_self_registered_dir(String &r_dotnet_root) {
|
|||
return false;
|
||||
}
|
||||
|
||||
r_dotnet_root = String::utf16((const char16_t *)buffer.ptr());
|
||||
r_dotnet_root = String::utf16((const char16_t *)buffer.ptr()).replace("\\", "/");
|
||||
RegCloseKey(hkey);
|
||||
return true;
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -1,16 +1,8 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
|
||||
import editor.template_builders as build_template_cs
|
||||
|
||||
env["BUILDERS"]["MakeCSharpTemplateBuilder"] = Builder(
|
||||
action=env.Run(build_template_cs.make_templates),
|
||||
suffix=".h",
|
||||
src_suffix=".cs",
|
||||
)
|
||||
|
||||
# Template files
|
||||
templates_sources = Glob("*/*.cs")
|
||||
|
||||
env.Alias("editor_template_cs", [env.MakeCSharpTemplateBuilder("templates.gen.h", templates_sources)])
|
||||
env.CommandNoCache("templates.gen.h", Glob("*/*.cs"), env.Run(build_template_cs.make_templates))
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
using _BINDINGS_NAMESPACE_;
|
||||
using System;
|
||||
|
||||
[Tool]
|
||||
[GlobalClass]
|
||||
public partial class VisualShaderNode_CLASS_ : _BASE_
|
||||
{
|
||||
public override string _GetName()
|
||||
|
|
@ -20,37 +22,37 @@ public partial class VisualShaderNode_CLASS_ : _BASE_
|
|||
return "";
|
||||
}
|
||||
|
||||
public override long _GetReturnIconType()
|
||||
public override VisualShaderNode.PortType _GetReturnIconType()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override long _GetInputPortCount()
|
||||
public override int _GetInputPortCount()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override string _GetInputPortName(long port)
|
||||
public override string _GetInputPortName(int port)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
public override long _GetInputPortType(long port)
|
||||
public override VisualShaderNode.PortType _GetInputPortType(int port)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public override long _GetOutputPortCount()
|
||||
public override int _GetOutputPortCount()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public override string _GetOutputPortName(long port)
|
||||
public override string _GetOutputPortName(int port)
|
||||
{
|
||||
return "result";
|
||||
}
|
||||
|
||||
public override long _GetOutputPortType(long port)
|
||||
public override VisualShaderNode.PortType _GetOutputPortType(int port)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#define SEMVER_H
|
||||
|
||||
#include "core/string/ustring.h"
|
||||
|
||||
#include "modules/regex/regex.h"
|
||||
|
||||
// <sys/sysmacros.h> is included somewhere, which defines major(dev) to gnu_dev_major(dev)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<LangVersion>10</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.10.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ using Godot.NativeInterop;
|
|||
{
|
||||
var parameter = callback.Parameters[i];
|
||||
|
||||
AppendRefKind(source, parameter.RefKind);
|
||||
AppendRefKind(source, parameter.RefKind, parameter.ScopedKind);
|
||||
source.Append(' ');
|
||||
source.Append(parameter.Type.FullQualifiedNameIncludeGlobal());
|
||||
source.Append(' ');
|
||||
|
|
@ -208,7 +208,7 @@ using Godot.NativeInterop;
|
|||
{
|
||||
// If it's a by-ref param and we can't get the pointer
|
||||
// just pass it by-ref and let it be pinned.
|
||||
AppendRefKind(methodCallArguments, parameter.RefKind)
|
||||
AppendRefKind(methodCallArguments, parameter.RefKind, parameter.ScopedKind)
|
||||
.Append(' ')
|
||||
.Append(parameter.Name);
|
||||
}
|
||||
|
|
@ -346,7 +346,7 @@ using Godot.NativeInterop;
|
|||
{
|
||||
// If it's a by-ref param and we can't get the pointer
|
||||
// just pass it by-ref and let it be pinned.
|
||||
AppendRefKind(source, parameter.RefKind)
|
||||
AppendRefKind(source, parameter.RefKind, parameter.ScopedKind)
|
||||
.Append(' ')
|
||||
.Append(parameter.Type.FullQualifiedNameIncludeGlobal());
|
||||
}
|
||||
|
|
@ -392,14 +392,18 @@ using Godot.NativeInterop;
|
|||
private static bool IsByRefParameter(IParameterSymbol parameter) =>
|
||||
parameter.RefKind is RefKind.In or RefKind.Out or RefKind.Ref;
|
||||
|
||||
private static StringBuilder AppendRefKind(StringBuilder source, RefKind refKind) =>
|
||||
refKind switch
|
||||
private static StringBuilder AppendRefKind(StringBuilder source, RefKind refKind, ScopedKind scopedKind)
|
||||
{
|
||||
return (refKind, scopedKind) switch
|
||||
{
|
||||
RefKind.In => source.Append("in"),
|
||||
RefKind.Out => source.Append("out"),
|
||||
RefKind.Ref => source.Append("ref"),
|
||||
(RefKind.Out, _) => source.Append("out"),
|
||||
(RefKind.In, ScopedKind.ScopedRef) => source.Append("scoped in"),
|
||||
(RefKind.In, _) => source.Append("in"),
|
||||
(RefKind.Ref, ScopedKind.ScopedRef) => source.Append("scoped ref"),
|
||||
(RefKind.Ref, _) => source.Append("ref"),
|
||||
_ => source,
|
||||
};
|
||||
}
|
||||
|
||||
private static void AppendPointerType(StringBuilder source, ITypeSymbol type)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<LangVersion>10</LangVersion>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
|
||||
|
|
|
|||
|
|
@ -314,13 +314,20 @@ namespace Godot
|
|||
/// <returns>A vector representing the support.</returns>
|
||||
public readonly Vector3 GetSupport(Vector3 dir)
|
||||
{
|
||||
Vector3 halfExtents = _size * 0.5f;
|
||||
Vector3 ofs = _position + halfExtents;
|
||||
|
||||
return ofs + new Vector3(
|
||||
dir.X > 0f ? halfExtents.X : -halfExtents.X,
|
||||
dir.Y > 0f ? halfExtents.Y : -halfExtents.Y,
|
||||
dir.Z > 0f ? halfExtents.Z : -halfExtents.Z);
|
||||
Vector3 support = _position;
|
||||
if (dir.X > 0.0f)
|
||||
{
|
||||
support.X += _size.X;
|
||||
}
|
||||
if (dir.Y > 0.0f)
|
||||
{
|
||||
support.Y += _size.Y;
|
||||
}
|
||||
if (dir.Z > 0.0f)
|
||||
{
|
||||
support.Z += _size.Z;
|
||||
}
|
||||
return support;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -50,8 +50,7 @@ namespace Godot.Collections
|
|||
/// <returns>A new Godot Array.</returns>
|
||||
public Array(IEnumerable<Variant> collection) : this()
|
||||
{
|
||||
if (collection == null)
|
||||
throw new ArgumentNullException(nameof(collection));
|
||||
ArgumentNullException.ThrowIfNull(collection);
|
||||
|
||||
foreach (Variant element in collection)
|
||||
Add(element);
|
||||
|
|
@ -67,8 +66,7 @@ namespace Godot.Collections
|
|||
/// <returns>A new Godot Array.</returns>
|
||||
public Array(Variant[] array)
|
||||
{
|
||||
if (array == null)
|
||||
throw new ArgumentNullException(nameof(array));
|
||||
ArgumentNullException.ThrowIfNull(array);
|
||||
|
||||
NativeValue = (godot_array.movable)NativeFuncs.godotsharp_array_new();
|
||||
_weakReferenceToSelf = DisposablesTracker.RegisterDisposable(this);
|
||||
|
|
@ -1046,6 +1044,8 @@ namespace Godot.Collections
|
|||
[DebuggerTypeProxy(typeof(ArrayDebugView<>))]
|
||||
[DebuggerDisplay("Count = {Count}")]
|
||||
[SuppressMessage("ReSharper", "RedundantExtendsListEntry")]
|
||||
[SuppressMessage("Design", "CA1001", MessageId = "Types that own disposable fields should be disposable",
|
||||
Justification = "Known issue. Requires explicit refcount management to not dispose untyped collections.")]
|
||||
[SuppressMessage("Naming", "CA1710", MessageId = "Identifiers should have correct suffix")]
|
||||
public sealed class Array<[MustBeVariant] T> :
|
||||
IList<T>,
|
||||
|
|
@ -1054,16 +1054,32 @@ namespace Godot.Collections
|
|||
IEnumerable<T>,
|
||||
IGenericGodotArray
|
||||
{
|
||||
private static godot_variant ToVariantFunc(in Array<T> godotArray) =>
|
||||
private static godot_variant ToVariantFunc(scoped in Array<T> godotArray) =>
|
||||
VariantUtils.CreateFromArray(godotArray);
|
||||
|
||||
private static Array<T> FromVariantFunc(in godot_variant variant) =>
|
||||
VariantUtils.ConvertToArray<T>(variant);
|
||||
|
||||
private void SetTypedForUnderlyingArray()
|
||||
{
|
||||
Marshaling.GetTypedCollectionParameterInfo<T>(out var elemVariantType, out var elemClassName, out var elemScriptRef);
|
||||
|
||||
var self = (godot_array)NativeValue;
|
||||
|
||||
using (elemScriptRef)
|
||||
{
|
||||
NativeFuncs.godotsharp_array_set_typed(
|
||||
ref self,
|
||||
(uint)elemVariantType,
|
||||
elemClassName,
|
||||
elemScriptRef);
|
||||
}
|
||||
}
|
||||
|
||||
static unsafe Array()
|
||||
{
|
||||
VariantUtils.GenericConversion<Array<T>>.ToVariantCb = &ToVariantFunc;
|
||||
VariantUtils.GenericConversion<Array<T>>.FromVariantCb = &FromVariantFunc;
|
||||
VariantUtils.GenericConversion<Array<T>>.ToVariantCb = ToVariantFunc;
|
||||
VariantUtils.GenericConversion<Array<T>>.FromVariantCb = FromVariantFunc;
|
||||
}
|
||||
|
||||
private readonly Array _underlyingArray;
|
||||
|
|
@ -1083,6 +1099,7 @@ namespace Godot.Collections
|
|||
public Array()
|
||||
{
|
||||
_underlyingArray = new Array();
|
||||
SetTypedForUnderlyingArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1095,10 +1112,10 @@ namespace Godot.Collections
|
|||
/// <returns>A new Godot Array.</returns>
|
||||
public Array(IEnumerable<T> collection)
|
||||
{
|
||||
if (collection == null)
|
||||
throw new ArgumentNullException(nameof(collection));
|
||||
ArgumentNullException.ThrowIfNull(collection);
|
||||
|
||||
_underlyingArray = new Array();
|
||||
SetTypedForUnderlyingArray();
|
||||
|
||||
foreach (T element in collection)
|
||||
Add(element);
|
||||
|
|
@ -1114,10 +1131,10 @@ namespace Godot.Collections
|
|||
/// <returns>A new Godot Array.</returns>
|
||||
public Array(T[] array)
|
||||
{
|
||||
if (array == null)
|
||||
throw new ArgumentNullException(nameof(array));
|
||||
ArgumentNullException.ThrowIfNull(array);
|
||||
|
||||
_underlyingArray = new Array();
|
||||
SetTypedForUnderlyingArray();
|
||||
|
||||
foreach (T element in array)
|
||||
Add(element);
|
||||
|
|
@ -1133,8 +1150,7 @@ namespace Godot.Collections
|
|||
/// <returns>A new Godot Array.</returns>
|
||||
public Array(Array array)
|
||||
{
|
||||
if (array == null)
|
||||
throw new ArgumentNullException(nameof(array));
|
||||
ArgumentNullException.ThrowIfNull(array);
|
||||
|
||||
_underlyingArray = array;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
using System;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Godot
|
||||
{
|
||||
/// <summary>
|
||||
/// Exports the annotated <see cref="Callable"/> as a clickable button.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public sealed class ExportToolButtonAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// The label of the button.
|
||||
/// </summary>
|
||||
public string Text { get; }
|
||||
|
||||
/// <summary>
|
||||
/// If defined, used to fetch an icon for the button via <see cref="Control.GetThemeIcon"/>,
|
||||
/// from the <code>EditorIcons</code> theme type.
|
||||
/// </summary>
|
||||
public string? Icon { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Exports the annotated <see cref="Callable"/> as a clickable button.
|
||||
/// </summary>
|
||||
/// <param name="text">The label of the button.</param>
|
||||
public ExportToolButtonAttribute(string text)
|
||||
{
|
||||
Text = text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -19,7 +19,7 @@ namespace Godot.Bridge
|
|||
public delegate* unmanaged<godot_string_name*, IntPtr, IntPtr> ScriptManagerBridge_CreateManagedForGodotObjectBinding;
|
||||
public delegate* unmanaged<IntPtr, IntPtr, godot_variant**, int, godot_bool> ScriptManagerBridge_CreateManagedForGodotObjectScriptInstance;
|
||||
public delegate* unmanaged<IntPtr, godot_string_name*, void> ScriptManagerBridge_GetScriptNativeName;
|
||||
public delegate* unmanaged<godot_string*, godot_string*, godot_string*, godot_string*, void> ScriptManagerBridge_GetGlobalClassName;
|
||||
public delegate* unmanaged<godot_string*, godot_string*, godot_string*, godot_bool*, godot_bool*, godot_string*, void> ScriptManagerBridge_GetGlobalClassName;
|
||||
public delegate* unmanaged<IntPtr, IntPtr, void> ScriptManagerBridge_SetGodotObjectPtr;
|
||||
public delegate* unmanaged<IntPtr, godot_string_name*, godot_variant**, int, godot_bool*, void> ScriptManagerBridge_RaiseEventSignal;
|
||||
public delegate* unmanaged<IntPtr, IntPtr, godot_bool> ScriptManagerBridge_ScriptIsOrInherits;
|
||||
|
|
|
|||
|
|
@ -90,30 +90,17 @@ namespace Godot.Bridge
|
|||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static unsafe IntPtr CreateManagedForGodotObjectBinding(godot_string_name* nativeTypeName,
|
||||
IntPtr godotObject)
|
||||
internal static unsafe IntPtr CreateManagedForGodotObjectBinding(godot_string_name* nativeTypeName, IntPtr godotObject)
|
||||
{
|
||||
// TODO: Optimize with source generators and delegate pointers.
|
||||
|
||||
try
|
||||
{
|
||||
using var stringName = StringName.CreateTakingOwnershipOfDisposableValue(
|
||||
NativeFuncs.godotsharp_string_name_new_copy(CustomUnsafe.AsRef(nativeTypeName)));
|
||||
string nativeTypeNameStr = stringName.ToString();
|
||||
|
||||
Type nativeType = TypeGetProxyClass(nativeTypeNameStr) ?? throw new InvalidOperationException(
|
||||
"Wrapper class not found for type: " + nativeTypeNameStr);
|
||||
var obj = (GodotObject)FormatterServices.GetUninitializedObject(nativeType);
|
||||
var instance = Constructors.Invoke(nativeTypeNameStr, godotObject);
|
||||
|
||||
var ctor = nativeType.GetConstructor(
|
||||
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
|
||||
null, Type.EmptyTypes, null);
|
||||
|
||||
obj.NativePtr = godotObject;
|
||||
|
||||
_ = ctor!.Invoke(obj, null);
|
||||
|
||||
return GCHandle.ToIntPtr(CustomGCHandle.AllocStrong(obj));
|
||||
return GCHandle.ToIntPtr(CustomGCHandle.AllocStrong(instance));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
@ -155,7 +142,7 @@ namespace Godot.Bridge
|
|||
}
|
||||
}
|
||||
|
||||
var obj = (GodotObject)FormatterServices.GetUninitializedObject(scriptType);
|
||||
var obj = (GodotObject)RuntimeHelpers.GetUninitializedObject(scriptType);
|
||||
|
||||
var parameters = ctor.GetParameters();
|
||||
int paramCount = parameters.Length;
|
||||
|
|
@ -194,18 +181,7 @@ namespace Godot.Bridge
|
|||
return;
|
||||
}
|
||||
|
||||
var native = GodotObject.InternalGetClassNativeBase(scriptType);
|
||||
|
||||
var field = native.GetField("NativeName", BindingFlags.DeclaredOnly | BindingFlags.Static |
|
||||
BindingFlags.Public | BindingFlags.NonPublic);
|
||||
|
||||
if (field == null)
|
||||
{
|
||||
*outRes = default;
|
||||
return;
|
||||
}
|
||||
|
||||
var nativeName = (StringName?)field.GetValue(null);
|
||||
var nativeName = GodotObject.InternalGetClassNativeBaseName(scriptType);
|
||||
|
||||
if (nativeName == null)
|
||||
{
|
||||
|
|
@ -223,7 +199,7 @@ namespace Godot.Bridge
|
|||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static unsafe void GetGlobalClassName(godot_string* scriptPath, godot_string* outBaseType, godot_string* outIconPath, godot_string* outClassName)
|
||||
internal static unsafe void GetGlobalClassName(godot_string* scriptPath, godot_string* outBaseType, godot_string* outIconPath, godot_bool* outIsAbstract, godot_bool* outIsTool, godot_string* outClassName)
|
||||
{
|
||||
// This method must always return the outBaseType for every script, even if the script is
|
||||
// not a global class. But if the script is not a global class it must return an empty
|
||||
|
|
@ -241,11 +217,17 @@ namespace Godot.Bridge
|
|||
|
||||
if (outIconPath != null)
|
||||
{
|
||||
var iconAttr = scriptType.GetCustomAttributes(inherit: false)
|
||||
IconAttribute? iconAttr = scriptType.GetCustomAttributes(inherit: false)
|
||||
.OfType<IconAttribute>()
|
||||
.FirstOrDefault();
|
||||
|
||||
*outIconPath = Marshaling.ConvertStringToNative(iconAttr?.Path);
|
||||
if (!string.IsNullOrEmpty(iconAttr?.Path))
|
||||
{
|
||||
string iconPath = iconAttr.Path.IsAbsolutePath()
|
||||
? iconAttr.Path.SimplifyPath()
|
||||
: scriptPathStr.GetBaseDir().PathJoin(iconAttr.Path).SimplifyPath();
|
||||
*outIconPath = Marshaling.ConvertStringToNative(iconPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (outBaseType != null)
|
||||
|
|
@ -272,6 +254,16 @@ namespace Godot.Bridge
|
|||
}
|
||||
}
|
||||
|
||||
if (outIsAbstract != null)
|
||||
{
|
||||
*outIsAbstract = scriptType.IsAbstract.ToGodotBool();
|
||||
}
|
||||
|
||||
if (outIsTool != null)
|
||||
{
|
||||
*outIsTool = Attribute.IsDefined(scriptType, typeof(ToolAttribute)).ToGodotBool();
|
||||
}
|
||||
|
||||
if (!IsGlobalClass(scriptType))
|
||||
{
|
||||
// Scripts that are not global classes should not have a name.
|
||||
|
|
@ -302,66 +294,6 @@ namespace Godot.Bridge
|
|||
}
|
||||
}
|
||||
|
||||
private static Type? TypeGetProxyClass(string nativeTypeNameStr)
|
||||
{
|
||||
// Performance is not critical here as this will be replaced with a generated dictionary.
|
||||
|
||||
if (nativeTypeNameStr[0] == '_')
|
||||
nativeTypeNameStr = nativeTypeNameStr.Substring(1);
|
||||
|
||||
Type? wrapperType = typeof(GodotObject).Assembly.GetType("Godot." + nativeTypeNameStr);
|
||||
|
||||
if (wrapperType == null)
|
||||
{
|
||||
wrapperType = GetTypeByGodotClassAttr(typeof(GodotObject).Assembly, nativeTypeNameStr);
|
||||
}
|
||||
|
||||
if (wrapperType == null)
|
||||
{
|
||||
var editorAssembly = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.FirstOrDefault(a => a.GetName().Name == "GodotSharpEditor");
|
||||
|
||||
if (editorAssembly != null)
|
||||
{
|
||||
wrapperType = editorAssembly.GetType("Godot." + nativeTypeNameStr);
|
||||
|
||||
if (wrapperType == null)
|
||||
{
|
||||
wrapperType = GetTypeByGodotClassAttr(editorAssembly, nativeTypeNameStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Type? GetTypeByGodotClassAttr(Assembly assembly, string nativeTypeNameStr)
|
||||
{
|
||||
var types = assembly.GetTypes();
|
||||
foreach (var type in types)
|
||||
{
|
||||
var attr = type.GetCustomAttribute<GodotClassNameAttribute>();
|
||||
if (attr?.Name == nativeTypeNameStr)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static bool IsStatic(Type type) => type.IsAbstract && type.IsSealed;
|
||||
|
||||
if (wrapperType != null && IsStatic(wrapperType))
|
||||
{
|
||||
// A static class means this is a Godot singleton class. Try to get the Instance proxy type.
|
||||
wrapperType = TypeGetProxyClass($"{wrapperType.Name}Instance");
|
||||
if (wrapperType == null)
|
||||
{
|
||||
// Otherwise, fallback to GodotObject.
|
||||
return typeof(GodotObject);
|
||||
}
|
||||
}
|
||||
|
||||
return wrapperType;
|
||||
}
|
||||
|
||||
// Called from GodotPlugins
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
public static void LookupScriptsInAssembly(Assembly assembly)
|
||||
|
|
@ -499,16 +431,29 @@ namespace Godot.Bridge
|
|||
|
||||
private static unsafe bool AddScriptBridgeCore(IntPtr scriptPtr, string scriptPath)
|
||||
{
|
||||
lock (_scriptTypeBiMap.ReadWriteLock)
|
||||
_scriptTypeBiMap.ReadWriteLock.EnterUpgradeableReadLock();
|
||||
try
|
||||
{
|
||||
if (!_scriptTypeBiMap.IsScriptRegistered(scriptPtr))
|
||||
{
|
||||
if (!_pathTypeBiMap.TryGetScriptType(scriptPath, out Type? scriptType))
|
||||
return false;
|
||||
|
||||
_scriptTypeBiMap.Add(scriptPtr, scriptType);
|
||||
_scriptTypeBiMap.ReadWriteLock.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
_scriptTypeBiMap.Add(scriptPtr, scriptType);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_scriptTypeBiMap.ReadWriteLock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_scriptTypeBiMap.ReadWriteLock.ExitUpgradeableReadLock();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -531,7 +476,8 @@ namespace Godot.Bridge
|
|||
|
||||
private static unsafe void GetOrCreateScriptBridgeForType(Type scriptType, godot_ref* outScript)
|
||||
{
|
||||
lock (_scriptTypeBiMap.ReadWriteLock)
|
||||
_scriptTypeBiMap.ReadWriteLock.EnterUpgradeableReadLock();
|
||||
try
|
||||
{
|
||||
if (_scriptTypeBiMap.TryGetScriptPtr(scriptType, out IntPtr scriptPtr))
|
||||
{
|
||||
|
|
@ -543,6 +489,10 @@ namespace Godot.Bridge
|
|||
// This path is slower, but it's only executed for the first instantiation of the type
|
||||
CreateScriptBridgeForType(scriptType, outScript);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_scriptTypeBiMap.ReadWriteLock.ExitUpgradeableReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
internal static unsafe void GetOrLoadOrCreateScriptForType(Type scriptType, godot_ref* outScript)
|
||||
|
|
@ -550,7 +500,8 @@ namespace Godot.Bridge
|
|||
static bool GetPathOtherwiseGetOrCreateScript(Type scriptType, godot_ref* outScript,
|
||||
[MaybeNullWhen(false)] out string scriptPath)
|
||||
{
|
||||
lock (_scriptTypeBiMap.ReadWriteLock)
|
||||
_scriptTypeBiMap.ReadWriteLock.EnterUpgradeableReadLock();
|
||||
try
|
||||
{
|
||||
if (_scriptTypeBiMap.TryGetScriptPtr(scriptType, out IntPtr scriptPtr))
|
||||
{
|
||||
|
|
@ -578,6 +529,10 @@ namespace Godot.Bridge
|
|||
scriptPath = null;
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_scriptTypeBiMap.ReadWriteLock.ExitUpgradeableReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
static string GetVirtualConstructedGenericTypeScriptPath(Type scriptType, string scriptPath)
|
||||
|
|
@ -607,7 +562,16 @@ namespace Godot.Bridge
|
|||
// IMPORTANT: The virtual path must be added to _pathTypeBiMap before the first
|
||||
// load of the script, otherwise the loaded script won't be added to _scriptTypeBiMap.
|
||||
scriptPath = GetVirtualConstructedGenericTypeScriptPath(scriptType, scriptPath);
|
||||
_pathTypeBiMap.Add(scriptPath, scriptType);
|
||||
|
||||
_scriptTypeBiMap.ReadWriteLock.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
_pathTypeBiMap.Add(scriptPath, scriptType);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_scriptTypeBiMap.ReadWriteLock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
// This must be done outside the read-write lock, as the script resource loading can lock it
|
||||
|
|
@ -637,104 +601,119 @@ namespace Godot.Bridge
|
|||
{
|
||||
Debug.Assert(!scriptType.IsGenericTypeDefinition, $"Script type must be a constructed generic type or not generic at all. Type: {scriptType}.");
|
||||
|
||||
NativeFuncs.godotsharp_internal_new_csharp_script(outScript);
|
||||
IntPtr scriptPtr = outScript->Reference;
|
||||
_scriptTypeBiMap.ReadWriteLock.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
NativeFuncs.godotsharp_internal_new_csharp_script(outScript);
|
||||
IntPtr scriptPtr = outScript->Reference;
|
||||
|
||||
// Caller takes care of locking
|
||||
_scriptTypeBiMap.Add(scriptPtr, scriptType);
|
||||
_scriptTypeBiMap.Add(scriptPtr, scriptType);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_scriptTypeBiMap.ReadWriteLock.ExitWriteLock();
|
||||
}
|
||||
|
||||
NativeFuncs.godotsharp_internal_reload_registered_script(scriptPtr);
|
||||
NativeFuncs.godotsharp_internal_reload_registered_script(outScript->Reference);
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static void RemoveScriptBridge(IntPtr scriptPtr)
|
||||
{
|
||||
_scriptTypeBiMap.ReadWriteLock.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
lock (_scriptTypeBiMap.ReadWriteLock)
|
||||
{
|
||||
_scriptTypeBiMap.Remove(scriptPtr);
|
||||
}
|
||||
_scriptTypeBiMap.Remove(scriptPtr);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.LogException(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_scriptTypeBiMap.ReadWriteLock.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static godot_bool TryReloadRegisteredScriptWithClass(IntPtr scriptPtr)
|
||||
{
|
||||
_scriptTypeBiMap.ReadWriteLock.EnterUpgradeableReadLock();
|
||||
try
|
||||
{
|
||||
lock (_scriptTypeBiMap.ReadWriteLock)
|
||||
if (_scriptTypeBiMap.TryGetScriptType(scriptPtr, out _))
|
||||
{
|
||||
if (_scriptTypeBiMap.TryGetScriptType(scriptPtr, out _))
|
||||
{
|
||||
// NOTE:
|
||||
// Currently, we reload all scripts, not only the ones from the unloaded ALC.
|
||||
// As such, we need to handle this case instead of treating it as an error.
|
||||
NativeFuncs.godotsharp_internal_reload_registered_script(scriptPtr);
|
||||
return godot_bool.True;
|
||||
}
|
||||
|
||||
if (!_scriptDataForReload.TryGetValue(scriptPtr, out var dataForReload))
|
||||
{
|
||||
GD.PushError("Missing class qualified name for reloading script");
|
||||
return godot_bool.False;
|
||||
}
|
||||
|
||||
_ = _scriptDataForReload.TryRemove(scriptPtr, out _);
|
||||
|
||||
if (dataForReload.assemblyName == null)
|
||||
{
|
||||
GD.PushError(
|
||||
$"Missing assembly name of class '{dataForReload.classFullName}' for reloading script");
|
||||
return godot_bool.False;
|
||||
}
|
||||
|
||||
var scriptType = ReflectionUtils.FindTypeInLoadedAssemblies(dataForReload.assemblyName,
|
||||
dataForReload.classFullName);
|
||||
|
||||
if (scriptType == null)
|
||||
{
|
||||
// The class was removed, can't reload
|
||||
return godot_bool.False;
|
||||
}
|
||||
|
||||
if (!typeof(GodotObject).IsAssignableFrom(scriptType))
|
||||
{
|
||||
// The class no longer inherits GodotObject, can't reload
|
||||
return godot_bool.False;
|
||||
}
|
||||
|
||||
_scriptTypeBiMap.Add(scriptPtr, scriptType);
|
||||
|
||||
// NOTE:
|
||||
// Currently, we reload all scripts, not only the ones from the unloaded ALC.
|
||||
// As such, we need to handle this case instead of treating it as an error.
|
||||
NativeFuncs.godotsharp_internal_reload_registered_script(scriptPtr);
|
||||
|
||||
return godot_bool.True;
|
||||
}
|
||||
|
||||
if (!_scriptDataForReload.TryGetValue(scriptPtr, out var dataForReload))
|
||||
{
|
||||
GD.PushError("Missing class qualified name for reloading script");
|
||||
return godot_bool.False;
|
||||
}
|
||||
|
||||
_ = _scriptDataForReload.TryRemove(scriptPtr, out _);
|
||||
|
||||
if (dataForReload.assemblyName == null)
|
||||
{
|
||||
GD.PushError(
|
||||
$"Missing assembly name of class '{dataForReload.classFullName}' for reloading script");
|
||||
return godot_bool.False;
|
||||
}
|
||||
|
||||
var scriptType = ReflectionUtils.FindTypeInLoadedAssemblies(dataForReload.assemblyName,
|
||||
dataForReload.classFullName);
|
||||
|
||||
if (scriptType == null)
|
||||
{
|
||||
// The class was removed, can't reload
|
||||
return godot_bool.False;
|
||||
}
|
||||
|
||||
if (!typeof(GodotObject).IsAssignableFrom(scriptType))
|
||||
{
|
||||
// The class no longer inherits GodotObject, can't reload
|
||||
return godot_bool.False;
|
||||
}
|
||||
|
||||
_scriptTypeBiMap.ReadWriteLock.EnterWriteLock();
|
||||
try
|
||||
{
|
||||
_scriptTypeBiMap.Add(scriptPtr, scriptType);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_scriptTypeBiMap.ReadWriteLock.ExitWriteLock();
|
||||
}
|
||||
|
||||
NativeFuncs.godotsharp_internal_reload_registered_script(scriptPtr);
|
||||
|
||||
return godot_bool.True;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.LogException(e);
|
||||
return godot_bool.False;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_scriptTypeBiMap.ReadWriteLock.ExitUpgradeableReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
private static unsafe void GetScriptTypeInfo(Type scriptType, godot_csharp_type_info* outTypeInfo)
|
||||
{
|
||||
Type native = GodotObject.InternalGetClassNativeBase(scriptType);
|
||||
godot_string className = Marshaling.ConvertStringToNative(ReflectionUtils.ConstructTypeName(scriptType));
|
||||
|
||||
string typeName = scriptType.Name;
|
||||
if (scriptType.IsGenericType)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
AppendTypeName(sb, scriptType);
|
||||
typeName = sb.ToString();
|
||||
}
|
||||
StringName? nativeBase = GodotObject.InternalGetClassNativeBaseName(scriptType);
|
||||
|
||||
godot_string className = Marshaling.ConvertStringToNative(typeName);
|
||||
godot_string_name nativeBaseName = nativeBase != null
|
||||
? NativeFuncs.godotsharp_string_name_new_copy((godot_string_name)nativeBase.NativeValue)
|
||||
: default;
|
||||
|
||||
bool isTool = scriptType.IsDefined(typeof(ToolAttribute), inherit: false);
|
||||
|
||||
|
|
@ -760,6 +739,7 @@ namespace Godot.Bridge
|
|||
godot_string iconPath = Marshaling.ConvertStringToNative(iconAttr?.Path);
|
||||
|
||||
outTypeInfo->ClassName = className;
|
||||
outTypeInfo->NativeBaseName = nativeBaseName;
|
||||
outTypeInfo->IconPath = iconPath;
|
||||
outTypeInfo->IsTool = isTool.ToGodotBool();
|
||||
outTypeInfo->IsGlobalClass = isGlobalClass.ToGodotBool();
|
||||
|
|
@ -767,24 +747,6 @@ namespace Godot.Bridge
|
|||
outTypeInfo->IsGenericTypeDefinition = scriptType.IsGenericTypeDefinition.ToGodotBool();
|
||||
outTypeInfo->IsConstructedGenericType = scriptType.IsConstructedGenericType.ToGodotBool();
|
||||
|
||||
static void AppendTypeName(StringBuilder sb, Type type)
|
||||
{
|
||||
sb.Append(type.Name);
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
sb.Append('<');
|
||||
for (int i = 0; i < type.GenericTypeArguments.Length; i++)
|
||||
{
|
||||
Type typeArg = type.GenericTypeArguments[i];
|
||||
AppendTypeName(sb, typeArg);
|
||||
if (i != type.GenericTypeArguments.Length - 1)
|
||||
{
|
||||
sb.Append(", ");
|
||||
}
|
||||
}
|
||||
sb.Append('>');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
|
|
@ -1098,7 +1060,7 @@ namespace Godot.Bridge
|
|||
interopProperties[i] = interopProperty;
|
||||
}
|
||||
|
||||
using godot_string currentClassName = Marshaling.ConvertStringToNative(type.Name);
|
||||
using godot_string currentClassName = Marshaling.ConvertStringToNative(ReflectionUtils.ConstructTypeName(type));
|
||||
|
||||
addPropInfoFunc(scriptPtr, ¤tClassName, interopProperties, length);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ using System.Diagnostics;
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace Godot.Bridge;
|
||||
|
||||
|
|
@ -11,9 +12,11 @@ namespace Godot.Bridge;
|
|||
|
||||
public static partial class ScriptManagerBridge
|
||||
{
|
||||
[SuppressMessage("Design", "CA1001", MessageId = "Types that own disposable fields should be disposable",
|
||||
Justification = "Not applicable. The class functions as a persistent singleton.")]
|
||||
private class ScriptTypeBiMap
|
||||
{
|
||||
public readonly object ReadWriteLock = new();
|
||||
public readonly ReaderWriterLockSlim ReadWriteLock = new(LockRecursionPolicy.SupportsRecursion);
|
||||
private System.Collections.Generic.Dictionary<IntPtr, Type> _scriptTypeMap = new();
|
||||
private System.Collections.Generic.Dictionary<Type, IntPtr> _typeScriptMap = new();
|
||||
|
||||
|
|
@ -65,7 +68,7 @@ public static partial class ScriptManagerBridge
|
|||
private System.Collections.Generic.Dictionary<string, Type> _pathTypeMap = new();
|
||||
private System.Collections.Generic.Dictionary<Type, string> _typePathMap = new();
|
||||
|
||||
public IReadOnlyCollection<string> Paths => _pathTypeMap.Keys;
|
||||
public System.Collections.Generic.Dictionary<string, Type>.KeyCollection Paths => _pathTypeMap.Keys;
|
||||
|
||||
public void Add(string scriptPath, Type scriptType)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -193,6 +193,51 @@ namespace Godot
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The OKHSL hue of this color, on the range 0 to 1.
|
||||
/// </summary>
|
||||
public float OkHslH
|
||||
{
|
||||
readonly get
|
||||
{
|
||||
return NativeFuncs.godotsharp_color_get_ok_hsl_h(this);
|
||||
}
|
||||
set
|
||||
{
|
||||
this = FromOkHsl(value, OkHslS, OkHslL, A);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The OKHSL saturation of this color, on the range 0 to 1.
|
||||
/// </summary>
|
||||
public float OkHslS
|
||||
{
|
||||
readonly get
|
||||
{
|
||||
return NativeFuncs.godotsharp_color_get_ok_hsl_s(this);
|
||||
}
|
||||
set
|
||||
{
|
||||
this = FromOkHsl(OkHslH, value, OkHslL, A);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The OKHSL lightness of this color, on the range 0 to 1.
|
||||
/// </summary>
|
||||
public float OkHslL
|
||||
{
|
||||
readonly get
|
||||
{
|
||||
return NativeFuncs.godotsharp_color_get_ok_hsl_l(this);
|
||||
}
|
||||
set
|
||||
{
|
||||
this = FromOkHsl(OkHslH, OkHslS, value, A);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the light intensity of the color, as a value between 0.0 and 1.0 (inclusive).
|
||||
/// This is useful when determining light or dark color. Colors with a luminance smaller
|
||||
|
|
|
|||
|
|
@ -87,8 +87,8 @@ namespace Godot
|
|||
|
||||
public void Resize(int size)
|
||||
{
|
||||
if (size < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(size));
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(size);
|
||||
|
||||
var err = NativeFuncs.godotsharp_stack_info_vector_resize(ref this, size);
|
||||
if (err != Error.Ok)
|
||||
throw new InvalidOperationException("Failed to resize vector. Error code is: " + err.ToString());
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ namespace Godot.Collections
|
|||
var keys = Array.CreateTakingOwnershipOfDisposableValue(keysArray);
|
||||
|
||||
godot_array valuesArray;
|
||||
NativeFuncs.godotsharp_dictionary_keys(ref self, out valuesArray);
|
||||
NativeFuncs.godotsharp_dictionary_values(ref self, out valuesArray);
|
||||
var values = Array.CreateTakingOwnershipOfDisposableValue(valuesArray);
|
||||
|
||||
int count = NativeFuncs.godotsharp_dictionary_count(ref self);
|
||||
|
|
@ -485,21 +485,44 @@ namespace Godot.Collections
|
|||
/// <typeparam name="TValue">The type of the dictionary's values.</typeparam>
|
||||
[DebuggerTypeProxy(typeof(DictionaryDebugView<,>))]
|
||||
[DebuggerDisplay("Count = {Count}")]
|
||||
[SuppressMessage("Design", "CA1001", MessageId = "Types that own disposable fields should be disposable",
|
||||
Justification = "Known issue. Requires explicit refcount management to not dispose untyped collections.")]
|
||||
public class Dictionary<[MustBeVariant] TKey, [MustBeVariant] TValue> :
|
||||
IDictionary<TKey, TValue>,
|
||||
IReadOnlyDictionary<TKey, TValue>,
|
||||
IGenericGodotDictionary
|
||||
{
|
||||
private static godot_variant ToVariantFunc(in Dictionary<TKey, TValue> godotDictionary) =>
|
||||
private static godot_variant ToVariantFunc(scoped in Dictionary<TKey, TValue> godotDictionary) =>
|
||||
VariantUtils.CreateFromDictionary(godotDictionary);
|
||||
|
||||
private static Dictionary<TKey, TValue> FromVariantFunc(in godot_variant variant) =>
|
||||
VariantUtils.ConvertToDictionary<TKey, TValue>(variant);
|
||||
|
||||
private void SetTypedForUnderlyingDictionary()
|
||||
{
|
||||
Marshaling.GetTypedCollectionParameterInfo<TKey>(out var keyVariantType, out var keyClassName, out var keyScriptRef);
|
||||
Marshaling.GetTypedCollectionParameterInfo<TValue>(out var valueVariantType, out var valueClassName, out var valueScriptRef);
|
||||
|
||||
var self = (godot_dictionary)NativeValue;
|
||||
|
||||
using (keyScriptRef)
|
||||
using (valueScriptRef)
|
||||
{
|
||||
NativeFuncs.godotsharp_dictionary_set_typed(
|
||||
ref self,
|
||||
(uint)keyVariantType,
|
||||
keyClassName,
|
||||
keyScriptRef,
|
||||
(uint)valueVariantType,
|
||||
valueClassName,
|
||||
valueScriptRef);
|
||||
}
|
||||
}
|
||||
|
||||
static unsafe Dictionary()
|
||||
{
|
||||
VariantUtils.GenericConversion<Dictionary<TKey, TValue>>.ToVariantCb = &ToVariantFunc;
|
||||
VariantUtils.GenericConversion<Dictionary<TKey, TValue>>.FromVariantCb = &FromVariantFunc;
|
||||
VariantUtils.GenericConversion<Dictionary<TKey, TValue>>.ToVariantCb = ToVariantFunc;
|
||||
VariantUtils.GenericConversion<Dictionary<TKey, TValue>>.FromVariantCb = FromVariantFunc;
|
||||
}
|
||||
|
||||
private readonly Dictionary _underlyingDict;
|
||||
|
|
@ -519,6 +542,7 @@ namespace Godot.Collections
|
|||
public Dictionary()
|
||||
{
|
||||
_underlyingDict = new Dictionary();
|
||||
SetTypedForUnderlyingDictionary();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -531,10 +555,10 @@ namespace Godot.Collections
|
|||
/// <returns>A new Godot Dictionary.</returns>
|
||||
public Dictionary(IDictionary<TKey, TValue> dictionary)
|
||||
{
|
||||
if (dictionary == null)
|
||||
throw new ArgumentNullException(nameof(dictionary));
|
||||
ArgumentNullException.ThrowIfNull(dictionary);
|
||||
|
||||
_underlyingDict = new Dictionary();
|
||||
SetTypedForUnderlyingDictionary();
|
||||
|
||||
foreach (KeyValuePair<TKey, TValue> entry in dictionary)
|
||||
Add(entry.Key, entry.Value);
|
||||
|
|
@ -550,8 +574,7 @@ namespace Godot.Collections
|
|||
/// <returns>A new Godot Dictionary.</returns>
|
||||
public Dictionary(Dictionary dictionary)
|
||||
{
|
||||
if (dictionary == null)
|
||||
throw new ArgumentNullException(nameof(dictionary));
|
||||
ArgumentNullException.ThrowIfNull(dictionary);
|
||||
|
||||
_underlyingDict = dictionary;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
#nullable enable
|
||||
|
|
@ -51,7 +52,7 @@ namespace Godot
|
|||
/// </summary>
|
||||
/// <param name="instance">The instance to check.</param>
|
||||
/// <returns>If the instance is a valid object.</returns>
|
||||
public static bool IsInstanceValid(GodotObject? instance)
|
||||
public static bool IsInstanceValid([NotNullWhen(true)] GodotObject? instance)
|
||||
{
|
||||
return instance != null && instance.NativeInstance != IntPtr.Zero;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using Godot.Bridge;
|
||||
using Godot.NativeInterop;
|
||||
|
|
@ -13,6 +15,8 @@ namespace Godot
|
|||
private bool _disposed;
|
||||
private static readonly Type _cachedType = typeof(GodotObject);
|
||||
|
||||
private static readonly Dictionary<Type, StringName?> _nativeNames = new Dictionary<Type, StringName?>();
|
||||
|
||||
internal IntPtr NativePtr;
|
||||
private bool _memoryOwn;
|
||||
|
||||
|
|
@ -29,8 +33,19 @@ namespace Godot
|
|||
}
|
||||
}
|
||||
|
||||
internal GodotObject(IntPtr nativePtr) : this(false)
|
||||
{
|
||||
// NativePtr must be non-zero before calling ConstructAndInitialize to avoid invoking the constructor NativeCtor.
|
||||
// We don't want to invoke the constructor, because we already have a constructed instance in nativePtr.
|
||||
NativePtr = nativePtr;
|
||||
unsafe
|
||||
{
|
||||
ConstructAndInitialize(NativeCtor, NativeName, _cachedType, refCounted: false);
|
||||
}
|
||||
}
|
||||
|
||||
internal unsafe void ConstructAndInitialize(
|
||||
delegate* unmanaged<IntPtr> nativeCtor,
|
||||
delegate* unmanaged<godot_bool, IntPtr> nativeCtor,
|
||||
StringName nativeName,
|
||||
Type cachedType,
|
||||
bool refCounted
|
||||
|
|
@ -40,7 +55,8 @@ namespace Godot
|
|||
{
|
||||
Debug.Assert(nativeCtor != null);
|
||||
|
||||
NativePtr = nativeCtor();
|
||||
// Need postinitialization.
|
||||
NativePtr = nativeCtor(godot_bool.True);
|
||||
|
||||
InteropUtils.TieManagedToUnmanaged(this, NativePtr,
|
||||
nativeName, refCounted, GetType(), cachedType);
|
||||
|
|
@ -74,8 +90,7 @@ namespace Godot
|
|||
// NativePtr is assigned, that would result in UB or crashes when calling
|
||||
// native functions that receive the pointer, which can happen because the
|
||||
// debugger calls ToString() and tries to get the value of properties.
|
||||
if (instance._disposed || instance.NativePtr == IntPtr.Zero)
|
||||
throw new ObjectDisposedException(instance.GetType().FullName);
|
||||
ObjectDisposedException.ThrowIf(instance._disposed || instance.NativePtr == IntPtr.Zero, instance);
|
||||
|
||||
return instance.NativePtr;
|
||||
}
|
||||
|
|
@ -179,16 +194,56 @@ namespace Godot
|
|||
return new SignalAwaiter(source, signal, this);
|
||||
}
|
||||
|
||||
internal static bool IsNativeClass(Type t)
|
||||
{
|
||||
if (ReferenceEquals(t.Assembly, typeof(GodotObject).Assembly))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ReflectionUtils.IsEditorHintCached)
|
||||
{
|
||||
return t.Assembly.GetName().Name == "GodotSharpEditor";
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static Type InternalGetClassNativeBase(Type t)
|
||||
{
|
||||
var name = t.Assembly.GetName().Name;
|
||||
while (!IsNativeClass(t))
|
||||
{
|
||||
Debug.Assert(t.BaseType is not null, "Script types must derive from a native Godot type.");
|
||||
|
||||
if (name == "GodotSharp" || name == "GodotSharpEditor")
|
||||
return t;
|
||||
t = t.BaseType;
|
||||
}
|
||||
|
||||
Debug.Assert(t.BaseType is not null, "Script types must derive from a native Godot type.");
|
||||
return t;
|
||||
}
|
||||
|
||||
return InternalGetClassNativeBase(t.BaseType);
|
||||
internal static StringName? InternalGetClassNativeBaseName(Type t)
|
||||
{
|
||||
if (_nativeNames.TryGetValue(t, out var name))
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
var baseType = InternalGetClassNativeBase(t);
|
||||
|
||||
if (_nativeNames.TryGetValue(baseType, out name))
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
var field = baseType.GetField("NativeName",
|
||||
BindingFlags.DeclaredOnly | BindingFlags.Static |
|
||||
BindingFlags.Public | BindingFlags.NonPublic);
|
||||
|
||||
name = field?.GetValue(null) as StringName;
|
||||
|
||||
_nativeNames[baseType] = name;
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
// ReSharper disable once VirtualMemberNeverOverridden.Global
|
||||
|
|
@ -260,7 +315,7 @@ namespace Godot
|
|||
return methodBind;
|
||||
}
|
||||
|
||||
internal static unsafe delegate* unmanaged<IntPtr> ClassDB_get_constructor(StringName type)
|
||||
internal static unsafe delegate* unmanaged<godot_bool, IntPtr> ClassDB_get_constructor(StringName type)
|
||||
{
|
||||
// for some reason the '??' operator doesn't support 'delegate*'
|
||||
var typeSelf = (godot_string_name)type.NativeValue;
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ namespace Godot
|
|||
|
||||
lock (_tasks)
|
||||
{
|
||||
if (_tasks.Any())
|
||||
if (_tasks.Count > 0)
|
||||
{
|
||||
task = _tasks.First.Value;
|
||||
_tasks.RemoveFirst();
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ namespace Godot.NativeInterop
|
|||
public ref struct godot_csharp_type_info
|
||||
{
|
||||
private godot_string _className;
|
||||
private godot_string_name _nativeBaseName;
|
||||
private godot_string _iconPath;
|
||||
private godot_bool _isTool;
|
||||
private godot_bool _isGlobalClass;
|
||||
|
|
@ -122,6 +123,12 @@ namespace Godot.NativeInterop
|
|||
set => _className = value;
|
||||
}
|
||||
|
||||
public godot_string_name NativeBaseName
|
||||
{
|
||||
readonly get => _nativeBaseName;
|
||||
set => _nativeBaseName = value;
|
||||
}
|
||||
|
||||
public godot_string IconPath
|
||||
{
|
||||
readonly get => _iconPath;
|
||||
|
|
@ -167,6 +174,7 @@ namespace Godot.NativeInterop
|
|||
=> (godot_variant*)Unsafe.AsPointer(ref Unsafe.AsRef(in _typeField));
|
||||
|
||||
// Variant.Type is generated as an enum of type long, so we can't use for the field as it must only take 32-bits.
|
||||
// The native enum actually has no fixed underlying type, so it is only at least 6 bits long.
|
||||
private int _typeField;
|
||||
|
||||
// There's padding here
|
||||
|
|
@ -474,8 +482,10 @@ namespace Godot.NativeInterop
|
|||
Type = Variant.Type.Nil;
|
||||
}
|
||||
|
||||
#pragma warning disable CS8981 // The type name only contains lower-cased ascii characters
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
internal struct movable
|
||||
#pragma warning restore CS8981
|
||||
{
|
||||
// Variant.Type is generated as an enum of type long, so we can't use for the field as it must only take 32-bits.
|
||||
[FieldOffset(0)] private int _typeField;
|
||||
|
|
@ -581,8 +591,10 @@ namespace Godot.NativeInterop
|
|||
return _data.GetHashCode();
|
||||
}
|
||||
|
||||
#pragma warning disable CS8981 // The type name only contains lower-cased ascii characters
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct movable
|
||||
#pragma warning restore CS8981
|
||||
{
|
||||
private IntPtr _data;
|
||||
|
||||
|
|
@ -627,8 +639,10 @@ namespace Godot.NativeInterop
|
|||
get => _data == IntPtr.Zero;
|
||||
}
|
||||
|
||||
#pragma warning disable CS8981 // The type name only contains lower-cased ascii characters
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct movable
|
||||
#pragma warning restore CS8981
|
||||
{
|
||||
private IntPtr _data;
|
||||
|
||||
|
|
@ -802,8 +816,10 @@ namespace Godot.NativeInterop
|
|||
_p = null;
|
||||
}
|
||||
|
||||
#pragma warning disable CS8981 // The type name only contains lower-cased ascii characters
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct movable
|
||||
#pragma warning restore CS8981
|
||||
{
|
||||
private unsafe ArrayPrivate* _p;
|
||||
|
||||
|
|
@ -869,8 +885,10 @@ namespace Godot.NativeInterop
|
|||
_p = null;
|
||||
}
|
||||
|
||||
#pragma warning disable CS8981 // The type name only contains lower-cased ascii characters
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct movable
|
||||
#pragma warning restore CS8981
|
||||
{
|
||||
private unsafe DictionaryPrivate* _p;
|
||||
|
||||
|
|
|
|||
|
|
@ -199,6 +199,44 @@ namespace Godot.NativeInterop
|
|||
return Variant.Type.Nil;
|
||||
}
|
||||
|
||||
internal static void GetTypedCollectionParameterInfo<T>(
|
||||
out Variant.Type variantType,
|
||||
out godot_string_name className,
|
||||
out godot_ref script)
|
||||
{
|
||||
variantType = ConvertManagedTypeToVariantType(typeof(T), out _);
|
||||
|
||||
if (variantType != Variant.Type.Object)
|
||||
{
|
||||
className = default;
|
||||
script = default;
|
||||
return;
|
||||
}
|
||||
|
||||
godot_ref scriptRef = default;
|
||||
|
||||
if (!GodotObject.IsNativeClass(typeof(T)))
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
Godot.Bridge.ScriptManagerBridge.GetOrLoadOrCreateScriptForType(typeof(T), &scriptRef);
|
||||
}
|
||||
|
||||
// Don't call GodotObject.InternalGetClassNativeBaseName here!
|
||||
// godot_dictionary_set_typed and godot_array_set_typed will call CSharpScript::get_instance_base_type
|
||||
// when a script is passed, because this is better for performance than using reflection to find the
|
||||
// native base type.
|
||||
className = default;
|
||||
}
|
||||
else
|
||||
{
|
||||
StringName? nativeBaseName = GodotObject.InternalGetClassNativeBaseName(typeof(T));
|
||||
className = nativeBaseName != null ? (godot_string_name)nativeBaseName.NativeValue : default;
|
||||
}
|
||||
|
||||
script = scriptRef;
|
||||
}
|
||||
|
||||
// String
|
||||
|
||||
public static unsafe godot_string ConvertStringToNative(string? p_mono_string)
|
||||
|
|
@ -230,7 +268,7 @@ namespace Godot.NativeInterop
|
|||
|
||||
// Callable
|
||||
|
||||
public static godot_callable ConvertCallableToNative(in Callable p_managed_callable)
|
||||
public static godot_callable ConvertCallableToNative(scoped in Callable p_managed_callable)
|
||||
{
|
||||
if (p_managed_callable.Delegate != null)
|
||||
{
|
||||
|
|
@ -295,7 +333,7 @@ namespace Godot.NativeInterop
|
|||
|
||||
// Signal
|
||||
|
||||
public static godot_signal ConvertSignalToNative(in Signal p_managed_signal)
|
||||
public static godot_signal ConvertSignalToNative(scoped in Signal p_managed_signal)
|
||||
{
|
||||
ulong ownerId = p_managed_signal.Owner.GetInstanceId();
|
||||
godot_string_name name;
|
||||
|
|
@ -394,7 +432,12 @@ namespace Godot.NativeInterop
|
|||
return array;
|
||||
}
|
||||
|
||||
public static unsafe godot_packed_byte_array ConvertSystemArrayToNativePackedByteArray(Span<byte> p_array)
|
||||
public static godot_packed_byte_array ConvertSystemArrayToNativePackedByteArray(scoped Span<byte> p_array)
|
||||
{
|
||||
return ConvertSystemArrayToNativePackedByteArray((ReadOnlySpan<byte>)p_array);
|
||||
}
|
||||
|
||||
public static unsafe godot_packed_byte_array ConvertSystemArrayToNativePackedByteArray(scoped ReadOnlySpan<byte> p_array)
|
||||
{
|
||||
if (p_array.IsEmpty)
|
||||
return new godot_packed_byte_array();
|
||||
|
|
@ -417,7 +460,12 @@ namespace Godot.NativeInterop
|
|||
return array;
|
||||
}
|
||||
|
||||
public static unsafe godot_packed_int32_array ConvertSystemArrayToNativePackedInt32Array(Span<int> p_array)
|
||||
public static godot_packed_int32_array ConvertSystemArrayToNativePackedInt32Array(scoped Span<int> p_array)
|
||||
{
|
||||
return ConvertSystemArrayToNativePackedInt32Array((ReadOnlySpan<int>)p_array);
|
||||
}
|
||||
|
||||
public static unsafe godot_packed_int32_array ConvertSystemArrayToNativePackedInt32Array(scoped ReadOnlySpan<int> p_array)
|
||||
{
|
||||
if (p_array.IsEmpty)
|
||||
return new godot_packed_int32_array();
|
||||
|
|
@ -440,7 +488,12 @@ namespace Godot.NativeInterop
|
|||
return array;
|
||||
}
|
||||
|
||||
public static unsafe godot_packed_int64_array ConvertSystemArrayToNativePackedInt64Array(Span<long> p_array)
|
||||
public static godot_packed_int64_array ConvertSystemArrayToNativePackedInt64Array(scoped Span<long> p_array)
|
||||
{
|
||||
return ConvertSystemArrayToNativePackedInt64Array((ReadOnlySpan<long>)p_array);
|
||||
}
|
||||
|
||||
public static unsafe godot_packed_int64_array ConvertSystemArrayToNativePackedInt64Array(scoped ReadOnlySpan<long> p_array)
|
||||
{
|
||||
if (p_array.IsEmpty)
|
||||
return new godot_packed_int64_array();
|
||||
|
|
@ -463,8 +516,12 @@ namespace Godot.NativeInterop
|
|||
return array;
|
||||
}
|
||||
|
||||
public static unsafe godot_packed_float32_array ConvertSystemArrayToNativePackedFloat32Array(
|
||||
Span<float> p_array)
|
||||
public static godot_packed_float32_array ConvertSystemArrayToNativePackedFloat32Array(scoped Span<float> p_array)
|
||||
{
|
||||
return ConvertSystemArrayToNativePackedFloat32Array((ReadOnlySpan<float>)p_array);
|
||||
}
|
||||
|
||||
public static unsafe godot_packed_float32_array ConvertSystemArrayToNativePackedFloat32Array(scoped ReadOnlySpan<float> p_array)
|
||||
{
|
||||
if (p_array.IsEmpty)
|
||||
return new godot_packed_float32_array();
|
||||
|
|
@ -487,8 +544,12 @@ namespace Godot.NativeInterop
|
|||
return array;
|
||||
}
|
||||
|
||||
public static unsafe godot_packed_float64_array ConvertSystemArrayToNativePackedFloat64Array(
|
||||
Span<double> p_array)
|
||||
public static godot_packed_float64_array ConvertSystemArrayToNativePackedFloat64Array(scoped Span<double> p_array)
|
||||
{
|
||||
return ConvertSystemArrayToNativePackedFloat64Array((ReadOnlySpan<double>)p_array);
|
||||
}
|
||||
|
||||
public static unsafe godot_packed_float64_array ConvertSystemArrayToNativePackedFloat64Array(scoped ReadOnlySpan<double> p_array)
|
||||
{
|
||||
if (p_array.IsEmpty)
|
||||
return new godot_packed_float64_array();
|
||||
|
|
@ -510,7 +571,12 @@ namespace Godot.NativeInterop
|
|||
return array;
|
||||
}
|
||||
|
||||
public static godot_packed_string_array ConvertSystemArrayToNativePackedStringArray(Span<string> p_array)
|
||||
public static godot_packed_string_array ConvertSystemArrayToNativePackedStringArray(scoped Span<string> p_array)
|
||||
{
|
||||
return ConvertSystemArrayToNativePackedStringArray((ReadOnlySpan<string>)p_array);
|
||||
}
|
||||
|
||||
public static godot_packed_string_array ConvertSystemArrayToNativePackedStringArray(scoped ReadOnlySpan<string> p_array)
|
||||
{
|
||||
godot_packed_string_array dest = new godot_packed_string_array();
|
||||
|
||||
|
|
@ -544,8 +610,12 @@ namespace Godot.NativeInterop
|
|||
return array;
|
||||
}
|
||||
|
||||
public static unsafe godot_packed_vector2_array ConvertSystemArrayToNativePackedVector2Array(
|
||||
Span<Vector2> p_array)
|
||||
public static godot_packed_vector2_array ConvertSystemArrayToNativePackedVector2Array(scoped Span<Vector2> p_array)
|
||||
{
|
||||
return ConvertSystemArrayToNativePackedVector2Array((ReadOnlySpan<Vector2>)p_array);
|
||||
}
|
||||
|
||||
public static unsafe godot_packed_vector2_array ConvertSystemArrayToNativePackedVector2Array(scoped ReadOnlySpan<Vector2> p_array)
|
||||
{
|
||||
if (p_array.IsEmpty)
|
||||
return new godot_packed_vector2_array();
|
||||
|
|
@ -568,8 +638,12 @@ namespace Godot.NativeInterop
|
|||
return array;
|
||||
}
|
||||
|
||||
public static unsafe godot_packed_vector3_array ConvertSystemArrayToNativePackedVector3Array(
|
||||
Span<Vector3> p_array)
|
||||
public static godot_packed_vector3_array ConvertSystemArrayToNativePackedVector3Array(scoped Span<Vector3> p_array)
|
||||
{
|
||||
return ConvertSystemArrayToNativePackedVector3Array((ReadOnlySpan<Vector3>)p_array);
|
||||
}
|
||||
|
||||
public static unsafe godot_packed_vector3_array ConvertSystemArrayToNativePackedVector3Array(scoped ReadOnlySpan<Vector3> p_array)
|
||||
{
|
||||
if (p_array.IsEmpty)
|
||||
return new godot_packed_vector3_array();
|
||||
|
|
@ -592,8 +666,12 @@ namespace Godot.NativeInterop
|
|||
return array;
|
||||
}
|
||||
|
||||
public static unsafe godot_packed_vector4_array ConvertSystemArrayToNativePackedVector4Array(
|
||||
Span<Vector4> p_array)
|
||||
public static godot_packed_vector4_array ConvertSystemArrayToNativePackedVector4Array(scoped Span<Vector4> p_array)
|
||||
{
|
||||
return ConvertSystemArrayToNativePackedVector4Array((ReadOnlySpan<Vector4>)p_array);
|
||||
}
|
||||
|
||||
public static unsafe godot_packed_vector4_array ConvertSystemArrayToNativePackedVector4Array(scoped ReadOnlySpan<Vector4> p_array)
|
||||
{
|
||||
if (p_array.IsEmpty)
|
||||
return new godot_packed_vector4_array();
|
||||
|
|
@ -616,7 +694,12 @@ namespace Godot.NativeInterop
|
|||
return array;
|
||||
}
|
||||
|
||||
public static unsafe godot_packed_color_array ConvertSystemArrayToNativePackedColorArray(Span<Color> p_array)
|
||||
public static godot_packed_color_array ConvertSystemArrayToNativePackedColorArray(scoped Span<Color> p_array)
|
||||
{
|
||||
return ConvertSystemArrayToNativePackedColorArray((ReadOnlySpan<Color>)p_array);
|
||||
}
|
||||
|
||||
public static unsafe godot_packed_color_array ConvertSystemArrayToNativePackedColorArray(scoped ReadOnlySpan<Color> p_array)
|
||||
{
|
||||
if (p_array.IsEmpty)
|
||||
return new godot_packed_color_array();
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ namespace Godot.NativeInterop
|
|||
public static partial IntPtr godotsharp_method_bind_get_method_with_compatibility(
|
||||
in godot_string_name p_classname, in godot_string_name p_methodname, ulong p_hash);
|
||||
|
||||
public static partial delegate* unmanaged<IntPtr> godotsharp_get_class_constructor(
|
||||
public static partial delegate* unmanaged<godot_bool, IntPtr> godotsharp_get_class_constructor(
|
||||
in godot_string_name p_classname);
|
||||
|
||||
public static partial IntPtr godotsharp_engine_get_singleton(in godot_string p_name);
|
||||
|
|
@ -101,10 +101,10 @@ namespace Godot.NativeInterop
|
|||
|
||||
internal static partial void godotsharp_internal_reload_registered_script(IntPtr scriptPtr);
|
||||
|
||||
internal static partial void godotsharp_array_filter_godot_objects_by_native(in godot_string_name p_native_name,
|
||||
in godot_array p_input, out godot_array r_output);
|
||||
internal static partial void godotsharp_array_filter_godot_objects_by_native(scoped in godot_string_name p_native_name,
|
||||
scoped in godot_array p_input, out godot_array r_output);
|
||||
|
||||
internal static partial void godotsharp_array_filter_godot_objects_by_non_native(in godot_array p_input,
|
||||
internal static partial void godotsharp_array_filter_godot_objects_by_non_native(scoped in godot_array p_input,
|
||||
out godot_array r_output);
|
||||
|
||||
public static partial void godotsharp_ref_new_from_ref_counted_ptr(out godot_ref r_dest,
|
||||
|
|
@ -113,15 +113,15 @@ namespace Godot.NativeInterop
|
|||
public static partial void godotsharp_ref_destroy(ref godot_ref p_instance);
|
||||
|
||||
public static partial void godotsharp_string_name_new_from_string(out godot_string_name r_dest,
|
||||
in godot_string p_name);
|
||||
scoped in godot_string p_name);
|
||||
|
||||
public static partial void godotsharp_node_path_new_from_string(out godot_node_path r_dest,
|
||||
in godot_string p_name);
|
||||
scoped in godot_string p_name);
|
||||
|
||||
public static partial void
|
||||
godotsharp_string_name_as_string(out godot_string r_dest, in godot_string_name p_name);
|
||||
godotsharp_string_name_as_string(out godot_string r_dest, scoped in godot_string_name p_name);
|
||||
|
||||
public static partial void godotsharp_node_path_as_string(out godot_string r_dest, in godot_node_path p_np);
|
||||
public static partial void godotsharp_node_path_as_string(out godot_string r_dest, scoped in godot_node_path p_np);
|
||||
|
||||
public static partial godot_packed_byte_array godotsharp_packed_byte_array_new_mem_copy(byte* p_src,
|
||||
int p_length);
|
||||
|
|
@ -156,10 +156,10 @@ namespace Godot.NativeInterop
|
|||
public static partial void godotsharp_callable_new_with_delegate(IntPtr p_delegate_handle, IntPtr p_trampoline,
|
||||
IntPtr p_object, out godot_callable r_callable);
|
||||
|
||||
internal static partial godot_bool godotsharp_callable_get_data_for_marshalling(in godot_callable p_callable,
|
||||
internal static partial godot_bool godotsharp_callable_get_data_for_marshalling(scoped in godot_callable p_callable,
|
||||
out IntPtr r_delegate_handle, out IntPtr r_trampoline, out IntPtr r_object, out godot_string_name r_name);
|
||||
|
||||
internal static partial godot_variant godotsharp_callable_call(in godot_callable p_callable,
|
||||
internal static partial godot_variant godotsharp_callable_call(scoped in godot_callable p_callable,
|
||||
godot_variant** p_args, int p_arg_count, out godot_variant_call_error p_call_error);
|
||||
|
||||
internal static partial void godotsharp_callable_call_deferred(in godot_callable p_callable,
|
||||
|
|
@ -167,6 +167,12 @@ namespace Godot.NativeInterop
|
|||
|
||||
internal static partial Color godotsharp_color_from_ok_hsl(float p_h, float p_s, float p_l, float p_alpha);
|
||||
|
||||
internal static partial float godotsharp_color_get_ok_hsl_h(in Color p_self);
|
||||
|
||||
internal static partial float godotsharp_color_get_ok_hsl_s(in Color p_self);
|
||||
|
||||
internal static partial float godotsharp_color_get_ok_hsl_l(in Color p_self);
|
||||
|
||||
// GDNative functions
|
||||
|
||||
// gdnative.h
|
||||
|
|
@ -180,140 +186,135 @@ namespace Godot.NativeInterop
|
|||
// variant.h
|
||||
|
||||
public static partial void
|
||||
godotsharp_variant_new_string_name(out godot_variant r_dest, in godot_string_name p_s);
|
||||
godotsharp_variant_new_string_name(out godot_variant r_dest, scoped in godot_string_name p_s);
|
||||
|
||||
public static partial void godotsharp_variant_new_copy(out godot_variant r_dest, in godot_variant p_src);
|
||||
public static partial void godotsharp_variant_new_copy(out godot_variant r_dest, scoped in godot_variant p_src);
|
||||
|
||||
public static partial void godotsharp_variant_new_node_path(out godot_variant r_dest, in godot_node_path p_np);
|
||||
public static partial void godotsharp_variant_new_node_path(out godot_variant r_dest, scoped in godot_node_path p_np);
|
||||
|
||||
public static partial void godotsharp_variant_new_object(out godot_variant r_dest, IntPtr p_obj);
|
||||
|
||||
public static partial void godotsharp_variant_new_transform2d(out godot_variant r_dest, in Transform2D p_t2d);
|
||||
public static partial void godotsharp_variant_new_transform2d(out godot_variant r_dest, scoped in Transform2D p_t2d);
|
||||
|
||||
public static partial void godotsharp_variant_new_basis(out godot_variant r_dest, in Basis p_basis);
|
||||
public static partial void godotsharp_variant_new_basis(out godot_variant r_dest, scoped in Basis p_basis);
|
||||
|
||||
public static partial void godotsharp_variant_new_transform3d(out godot_variant r_dest, in Transform3D p_trans);
|
||||
public static partial void godotsharp_variant_new_transform3d(out godot_variant r_dest, scoped in Transform3D p_trans);
|
||||
|
||||
public static partial void godotsharp_variant_new_projection(out godot_variant r_dest, in Projection p_proj);
|
||||
public static partial void godotsharp_variant_new_projection(out godot_variant r_dest, scoped in Projection p_proj);
|
||||
|
||||
public static partial void godotsharp_variant_new_aabb(out godot_variant r_dest, in Aabb p_aabb);
|
||||
public static partial void godotsharp_variant_new_aabb(out godot_variant r_dest, scoped in Aabb p_aabb);
|
||||
|
||||
public static partial void godotsharp_variant_new_dictionary(out godot_variant r_dest,
|
||||
in godot_dictionary p_dict);
|
||||
scoped in godot_dictionary p_dict);
|
||||
|
||||
public static partial void godotsharp_variant_new_array(out godot_variant r_dest, in godot_array p_arr);
|
||||
public static partial void godotsharp_variant_new_array(out godot_variant r_dest, scoped in godot_array p_arr);
|
||||
|
||||
public static partial void godotsharp_variant_new_packed_byte_array(out godot_variant r_dest,
|
||||
in godot_packed_byte_array p_pba);
|
||||
scoped in godot_packed_byte_array p_pba);
|
||||
|
||||
public static partial void godotsharp_variant_new_packed_int32_array(out godot_variant r_dest,
|
||||
in godot_packed_int32_array p_pia);
|
||||
scoped in godot_packed_int32_array p_pia);
|
||||
|
||||
public static partial void godotsharp_variant_new_packed_int64_array(out godot_variant r_dest,
|
||||
in godot_packed_int64_array p_pia);
|
||||
scoped in godot_packed_int64_array p_pia);
|
||||
|
||||
public static partial void godotsharp_variant_new_packed_float32_array(out godot_variant r_dest,
|
||||
in godot_packed_float32_array p_pra);
|
||||
scoped in godot_packed_float32_array p_pra);
|
||||
|
||||
public static partial void godotsharp_variant_new_packed_float64_array(out godot_variant r_dest,
|
||||
in godot_packed_float64_array p_pra);
|
||||
scoped in godot_packed_float64_array p_pra);
|
||||
|
||||
public static partial void godotsharp_variant_new_packed_string_array(out godot_variant r_dest,
|
||||
in godot_packed_string_array p_psa);
|
||||
scoped in godot_packed_string_array p_psa);
|
||||
|
||||
public static partial void godotsharp_variant_new_packed_vector2_array(out godot_variant r_dest,
|
||||
in godot_packed_vector2_array p_pv2a);
|
||||
scoped in godot_packed_vector2_array p_pv2a);
|
||||
|
||||
public static partial void godotsharp_variant_new_packed_vector3_array(out godot_variant r_dest,
|
||||
in godot_packed_vector3_array p_pv3a);
|
||||
scoped in godot_packed_vector3_array p_pv3a);
|
||||
|
||||
public static partial void godotsharp_variant_new_packed_vector4_array(out godot_variant r_dest,
|
||||
in godot_packed_vector4_array p_pv4a);
|
||||
scoped in godot_packed_vector4_array p_pv4a);
|
||||
|
||||
public static partial void godotsharp_variant_new_packed_color_array(out godot_variant r_dest,
|
||||
in godot_packed_color_array p_pca);
|
||||
scoped in godot_packed_color_array p_pca);
|
||||
|
||||
public static partial godot_bool godotsharp_variant_as_bool(in godot_variant p_self);
|
||||
public static partial godot_bool godotsharp_variant_as_bool(scoped in godot_variant p_self);
|
||||
|
||||
public static partial Int64 godotsharp_variant_as_int(in godot_variant p_self);
|
||||
public static partial Int64 godotsharp_variant_as_int(scoped in godot_variant p_self);
|
||||
|
||||
public static partial double godotsharp_variant_as_float(in godot_variant p_self);
|
||||
public static partial double godotsharp_variant_as_float(scoped in godot_variant p_self);
|
||||
|
||||
public static partial godot_string godotsharp_variant_as_string(in godot_variant p_self);
|
||||
public static partial godot_string godotsharp_variant_as_string(scoped in godot_variant p_self);
|
||||
|
||||
public static partial Vector2 godotsharp_variant_as_vector2(in godot_variant p_self);
|
||||
public static partial Vector2 godotsharp_variant_as_vector2(scoped in godot_variant p_self);
|
||||
|
||||
public static partial Vector2I godotsharp_variant_as_vector2i(in godot_variant p_self);
|
||||
public static partial Vector2I godotsharp_variant_as_vector2i(scoped in godot_variant p_self);
|
||||
|
||||
public static partial Rect2 godotsharp_variant_as_rect2(in godot_variant p_self);
|
||||
public static partial Rect2 godotsharp_variant_as_rect2(scoped in godot_variant p_self);
|
||||
|
||||
public static partial Rect2I godotsharp_variant_as_rect2i(in godot_variant p_self);
|
||||
public static partial Rect2I godotsharp_variant_as_rect2i(scoped in godot_variant p_self);
|
||||
|
||||
public static partial Vector3 godotsharp_variant_as_vector3(in godot_variant p_self);
|
||||
public static partial Vector3 godotsharp_variant_as_vector3(scoped in godot_variant p_self);
|
||||
|
||||
public static partial Vector3I godotsharp_variant_as_vector3i(in godot_variant p_self);
|
||||
public static partial Vector3I godotsharp_variant_as_vector3i(scoped in godot_variant p_self);
|
||||
|
||||
public static partial Transform2D godotsharp_variant_as_transform2d(in godot_variant p_self);
|
||||
public static partial Transform2D godotsharp_variant_as_transform2d(scoped in godot_variant p_self);
|
||||
|
||||
public static partial Vector4 godotsharp_variant_as_vector4(in godot_variant p_self);
|
||||
public static partial Vector4 godotsharp_variant_as_vector4(scoped in godot_variant p_self);
|
||||
|
||||
public static partial Vector4I godotsharp_variant_as_vector4i(in godot_variant p_self);
|
||||
public static partial Vector4I godotsharp_variant_as_vector4i(scoped in godot_variant p_self);
|
||||
|
||||
public static partial Plane godotsharp_variant_as_plane(in godot_variant p_self);
|
||||
public static partial Plane godotsharp_variant_as_plane(scoped in godot_variant p_self);
|
||||
|
||||
public static partial Quaternion godotsharp_variant_as_quaternion(in godot_variant p_self);
|
||||
public static partial Quaternion godotsharp_variant_as_quaternion(scoped in godot_variant p_self);
|
||||
|
||||
public static partial Aabb godotsharp_variant_as_aabb(in godot_variant p_self);
|
||||
public static partial Aabb godotsharp_variant_as_aabb(scoped in godot_variant p_self);
|
||||
|
||||
public static partial Basis godotsharp_variant_as_basis(in godot_variant p_self);
|
||||
public static partial Basis godotsharp_variant_as_basis(scoped in godot_variant p_self);
|
||||
|
||||
public static partial Transform3D godotsharp_variant_as_transform3d(in godot_variant p_self);
|
||||
public static partial Transform3D godotsharp_variant_as_transform3d(scoped in godot_variant p_self);
|
||||
|
||||
public static partial Projection godotsharp_variant_as_projection(in godot_variant p_self);
|
||||
public static partial Projection godotsharp_variant_as_projection(scoped in godot_variant p_self);
|
||||
|
||||
public static partial Color godotsharp_variant_as_color(in godot_variant p_self);
|
||||
public static partial Color godotsharp_variant_as_color(scoped in godot_variant p_self);
|
||||
|
||||
public static partial godot_string_name godotsharp_variant_as_string_name(in godot_variant p_self);
|
||||
public static partial godot_string_name godotsharp_variant_as_string_name(scoped in godot_variant p_self);
|
||||
|
||||
public static partial godot_node_path godotsharp_variant_as_node_path(in godot_variant p_self);
|
||||
public static partial godot_node_path godotsharp_variant_as_node_path(scoped in godot_variant p_self);
|
||||
|
||||
public static partial Rid godotsharp_variant_as_rid(in godot_variant p_self);
|
||||
public static partial Rid godotsharp_variant_as_rid(scoped in godot_variant p_self);
|
||||
|
||||
public static partial godot_callable godotsharp_variant_as_callable(in godot_variant p_self);
|
||||
public static partial godot_callable godotsharp_variant_as_callable(scoped in godot_variant p_self);
|
||||
|
||||
public static partial godot_signal godotsharp_variant_as_signal(in godot_variant p_self);
|
||||
public static partial godot_signal godotsharp_variant_as_signal(scoped in godot_variant p_self);
|
||||
|
||||
public static partial godot_dictionary godotsharp_variant_as_dictionary(in godot_variant p_self);
|
||||
public static partial godot_dictionary godotsharp_variant_as_dictionary(scoped in godot_variant p_self);
|
||||
|
||||
public static partial godot_array godotsharp_variant_as_array(in godot_variant p_self);
|
||||
public static partial godot_array godotsharp_variant_as_array(scoped in godot_variant p_self);
|
||||
|
||||
public static partial godot_packed_byte_array godotsharp_variant_as_packed_byte_array(in godot_variant p_self);
|
||||
public static partial godot_packed_byte_array godotsharp_variant_as_packed_byte_array(scoped in godot_variant p_self);
|
||||
|
||||
public static partial godot_packed_int32_array godotsharp_variant_as_packed_int32_array(in godot_variant p_self);
|
||||
public static partial godot_packed_int32_array godotsharp_variant_as_packed_int32_array(scoped in godot_variant p_self);
|
||||
|
||||
public static partial godot_packed_int64_array godotsharp_variant_as_packed_int64_array(in godot_variant p_self);
|
||||
public static partial godot_packed_int64_array godotsharp_variant_as_packed_int64_array(scoped in godot_variant p_self);
|
||||
|
||||
public static partial godot_packed_float32_array godotsharp_variant_as_packed_float32_array(
|
||||
in godot_variant p_self);
|
||||
public static partial godot_packed_float32_array godotsharp_variant_as_packed_float32_array(scoped in godot_variant p_self);
|
||||
|
||||
public static partial godot_packed_float64_array godotsharp_variant_as_packed_float64_array(
|
||||
in godot_variant p_self);
|
||||
public static partial godot_packed_float64_array godotsharp_variant_as_packed_float64_array(scoped in godot_variant p_self);
|
||||
|
||||
public static partial godot_packed_string_array godotsharp_variant_as_packed_string_array(
|
||||
in godot_variant p_self);
|
||||
public static partial godot_packed_string_array godotsharp_variant_as_packed_string_array(scoped in godot_variant p_self);
|
||||
|
||||
public static partial godot_packed_vector2_array godotsharp_variant_as_packed_vector2_array(
|
||||
in godot_variant p_self);
|
||||
public static partial godot_packed_vector2_array godotsharp_variant_as_packed_vector2_array(scoped in godot_variant p_self);
|
||||
|
||||
public static partial godot_packed_vector3_array godotsharp_variant_as_packed_vector3_array(
|
||||
in godot_variant p_self);
|
||||
public static partial godot_packed_vector3_array godotsharp_variant_as_packed_vector3_array(scoped in godot_variant p_self);
|
||||
|
||||
public static partial godot_packed_vector4_array godotsharp_variant_as_packed_vector4_array(
|
||||
in godot_variant p_self);
|
||||
|
||||
public static partial godot_packed_color_array godotsharp_variant_as_packed_color_array(in godot_variant p_self);
|
||||
public static partial godot_packed_color_array godotsharp_variant_as_packed_color_array(scoped in godot_variant p_self);
|
||||
|
||||
public static partial godot_bool godotsharp_variant_equals(in godot_variant p_a, in godot_variant p_b);
|
||||
public static partial godot_bool godotsharp_variant_equals(scoped in godot_variant p_a, scoped in godot_variant p_b);
|
||||
|
||||
// string.h
|
||||
|
||||
|
|
@ -322,17 +323,17 @@ namespace Godot.NativeInterop
|
|||
// string_name.h
|
||||
|
||||
public static partial void godotsharp_string_name_new_copy(out godot_string_name r_dest,
|
||||
in godot_string_name p_src);
|
||||
scoped in godot_string_name p_src);
|
||||
|
||||
// node_path.h
|
||||
|
||||
public static partial void godotsharp_node_path_new_copy(out godot_node_path r_dest, in godot_node_path p_src);
|
||||
public static partial void godotsharp_node_path_new_copy(out godot_node_path r_dest, scoped in godot_node_path p_src);
|
||||
|
||||
// array.h
|
||||
|
||||
public static partial void godotsharp_array_new(out godot_array r_dest);
|
||||
|
||||
public static partial void godotsharp_array_new_copy(out godot_array r_dest, in godot_array p_src);
|
||||
public static partial void godotsharp_array_new_copy(out godot_array r_dest, scoped in godot_array p_src);
|
||||
|
||||
public static partial godot_variant* godotsharp_array_ptrw(ref godot_array p_self);
|
||||
|
||||
|
|
@ -341,7 +342,7 @@ namespace Godot.NativeInterop
|
|||
public static partial void godotsharp_dictionary_new(out godot_dictionary r_dest);
|
||||
|
||||
public static partial void godotsharp_dictionary_new_copy(out godot_dictionary r_dest,
|
||||
in godot_dictionary p_src);
|
||||
scoped in godot_dictionary p_src);
|
||||
|
||||
// destroy functions
|
||||
|
||||
|
|
@ -389,8 +390,7 @@ namespace Godot.NativeInterop
|
|||
|
||||
public static partial int godotsharp_array_binary_search(ref godot_array p_self, int p_index, int p_count, in godot_variant p_value);
|
||||
|
||||
public static partial void
|
||||
godotsharp_array_duplicate(ref godot_array p_self, godot_bool p_deep, out godot_array r_dest);
|
||||
public static partial void godotsharp_array_duplicate(scoped ref godot_array p_self, godot_bool p_deep, out godot_array r_dest);
|
||||
|
||||
public static partial void godotsharp_array_fill(ref godot_array p_self, in godot_variant p_value);
|
||||
|
||||
|
|
@ -402,11 +402,19 @@ namespace Godot.NativeInterop
|
|||
|
||||
public static partial void godotsharp_array_make_read_only(ref godot_array p_self);
|
||||
|
||||
public static partial void godotsharp_array_max(ref godot_array p_self, out godot_variant r_value);
|
||||
public static partial void godotsharp_array_set_typed(
|
||||
ref godot_array p_self,
|
||||
uint p_elem_type,
|
||||
in godot_string_name p_elem_class_name,
|
||||
in godot_ref p_elem_script);
|
||||
|
||||
public static partial void godotsharp_array_min(ref godot_array p_self, out godot_variant r_value);
|
||||
public static partial godot_bool godotsharp_array_is_typed(ref godot_array p_self);
|
||||
|
||||
public static partial void godotsharp_array_pick_random(ref godot_array p_self, out godot_variant r_value);
|
||||
public static partial void godotsharp_array_max(scoped ref godot_array p_self, out godot_variant r_value);
|
||||
|
||||
public static partial void godotsharp_array_min(scoped ref godot_array p_self, out godot_variant r_value);
|
||||
|
||||
public static partial void godotsharp_array_pick_random(scoped ref godot_array p_self, out godot_variant r_value);
|
||||
|
||||
public static partial godot_bool godotsharp_array_recursive_equal(ref godot_array p_self, in godot_array p_other);
|
||||
|
||||
|
|
@ -418,7 +426,7 @@ namespace Godot.NativeInterop
|
|||
|
||||
public static partial void godotsharp_array_shuffle(ref godot_array p_self);
|
||||
|
||||
public static partial void godotsharp_array_slice(ref godot_array p_self, int p_start, int p_end,
|
||||
public static partial void godotsharp_array_slice(scoped ref godot_array p_self, int p_start, int p_end,
|
||||
int p_step, godot_bool p_deep, out godot_array r_dest);
|
||||
|
||||
public static partial void godotsharp_array_sort(ref godot_array p_self);
|
||||
|
|
@ -427,20 +435,20 @@ namespace Godot.NativeInterop
|
|||
|
||||
// Dictionary
|
||||
|
||||
public static partial godot_bool godotsharp_dictionary_try_get_value(ref godot_dictionary p_self,
|
||||
in godot_variant p_key,
|
||||
public static partial godot_bool godotsharp_dictionary_try_get_value(scoped ref godot_dictionary p_self,
|
||||
scoped in godot_variant p_key,
|
||||
out godot_variant r_value);
|
||||
|
||||
public static partial void godotsharp_dictionary_set_value(ref godot_dictionary p_self, in godot_variant p_key,
|
||||
in godot_variant p_value);
|
||||
|
||||
public static partial void godotsharp_dictionary_keys(ref godot_dictionary p_self, out godot_array r_dest);
|
||||
public static partial void godotsharp_dictionary_keys(scoped ref godot_dictionary p_self, out godot_array r_dest);
|
||||
|
||||
public static partial void godotsharp_dictionary_values(ref godot_dictionary p_self, out godot_array r_dest);
|
||||
public static partial void godotsharp_dictionary_values(scoped ref godot_dictionary p_self, out godot_array r_dest);
|
||||
|
||||
public static partial int godotsharp_dictionary_count(ref godot_dictionary p_self);
|
||||
|
||||
public static partial void godotsharp_dictionary_key_value_pair_at(ref godot_dictionary p_self, int p_index,
|
||||
public static partial void godotsharp_dictionary_key_value_pair_at(scoped ref godot_dictionary p_self, int p_index,
|
||||
out godot_variant r_key, out godot_variant r_value);
|
||||
|
||||
public static partial void godotsharp_dictionary_add(ref godot_dictionary p_self, in godot_variant p_key,
|
||||
|
|
@ -451,7 +459,7 @@ namespace Godot.NativeInterop
|
|||
public static partial godot_bool godotsharp_dictionary_contains_key(ref godot_dictionary p_self,
|
||||
in godot_variant p_key);
|
||||
|
||||
public static partial void godotsharp_dictionary_duplicate(ref godot_dictionary p_self, godot_bool p_deep,
|
||||
public static partial void godotsharp_dictionary_duplicate(scoped ref godot_dictionary p_self, godot_bool p_deep,
|
||||
out godot_dictionary r_dest);
|
||||
|
||||
public static partial void godotsharp_dictionary_merge(ref godot_dictionary p_self, in godot_dictionary p_dictionary, godot_bool p_overwrite);
|
||||
|
|
@ -463,20 +471,45 @@ namespace Godot.NativeInterop
|
|||
|
||||
public static partial void godotsharp_dictionary_make_read_only(ref godot_dictionary p_self);
|
||||
|
||||
public static partial void godotsharp_dictionary_to_string(ref godot_dictionary p_self, out godot_string r_str);
|
||||
public static partial void godotsharp_dictionary_set_typed(
|
||||
ref godot_dictionary p_self,
|
||||
uint p_key_type,
|
||||
in godot_string_name p_key_class_name,
|
||||
in godot_ref p_key_script,
|
||||
uint p_value_type,
|
||||
in godot_string_name p_value_class_name,
|
||||
in godot_ref p_value_script);
|
||||
|
||||
public static partial godot_bool godotsharp_dictionary_is_typed_key(ref godot_dictionary p_self);
|
||||
|
||||
public static partial godot_bool godotsharp_dictionary_is_typed_value(ref godot_dictionary p_self);
|
||||
|
||||
public static partial uint godotsharp_dictionary_get_typed_key_builtin(ref godot_dictionary p_self);
|
||||
|
||||
public static partial uint godotsharp_dictionary_get_typed_value_builtin(ref godot_dictionary p_self);
|
||||
|
||||
public static partial void godotsharp_dictionary_get_typed_key_class_name(ref godot_dictionary p_self, out godot_string_name r_dest);
|
||||
|
||||
public static partial void godotsharp_dictionary_get_typed_value_class_name(ref godot_dictionary p_self, out godot_string_name r_dest);
|
||||
|
||||
public static partial void godotsharp_dictionary_get_typed_key_script(ref godot_dictionary p_self, out godot_variant r_dest);
|
||||
|
||||
public static partial void godotsharp_dictionary_get_typed_value_script(ref godot_dictionary p_self, out godot_variant r_dest);
|
||||
|
||||
public static partial void godotsharp_dictionary_to_string(scoped ref godot_dictionary p_self, out godot_string r_str);
|
||||
|
||||
// StringExtensions
|
||||
|
||||
public static partial void godotsharp_string_simplify_path(in godot_string p_self,
|
||||
public static partial void godotsharp_string_simplify_path(scoped in godot_string p_self,
|
||||
out godot_string r_simplified_path);
|
||||
|
||||
public static partial void godotsharp_string_to_camel_case(in godot_string p_self,
|
||||
public static partial void godotsharp_string_to_camel_case(scoped in godot_string p_self,
|
||||
out godot_string r_camel_case);
|
||||
|
||||
public static partial void godotsharp_string_to_pascal_case(in godot_string p_self,
|
||||
public static partial void godotsharp_string_to_pascal_case(scoped in godot_string p_self,
|
||||
out godot_string r_pascal_case);
|
||||
|
||||
public static partial void godotsharp_string_to_snake_case(in godot_string p_self,
|
||||
public static partial void godotsharp_string_to_snake_case(scoped in godot_string p_self,
|
||||
out godot_string r_snake_case);
|
||||
|
||||
// NodePath
|
||||
|
|
@ -484,18 +517,18 @@ namespace Godot.NativeInterop
|
|||
public static partial void godotsharp_node_path_get_as_property_path(in godot_node_path p_self,
|
||||
ref godot_node_path r_dest);
|
||||
|
||||
public static partial void godotsharp_node_path_get_concatenated_names(in godot_node_path p_self,
|
||||
public static partial void godotsharp_node_path_get_concatenated_names(scoped in godot_node_path p_self,
|
||||
out godot_string r_names);
|
||||
|
||||
public static partial void godotsharp_node_path_get_concatenated_subnames(in godot_node_path p_self,
|
||||
public static partial void godotsharp_node_path_get_concatenated_subnames(scoped in godot_node_path p_self,
|
||||
out godot_string r_subnames);
|
||||
|
||||
public static partial void godotsharp_node_path_get_name(in godot_node_path p_self, int p_idx,
|
||||
public static partial void godotsharp_node_path_get_name(scoped in godot_node_path p_self, int p_idx,
|
||||
out godot_string r_name);
|
||||
|
||||
public static partial int godotsharp_node_path_get_name_count(in godot_node_path p_self);
|
||||
|
||||
public static partial void godotsharp_node_path_get_subname(in godot_node_path p_self, int p_idx,
|
||||
public static partial void godotsharp_node_path_get_subname(scoped in godot_node_path p_self, int p_idx,
|
||||
out godot_string r_subname);
|
||||
|
||||
public static partial int godotsharp_node_path_get_subname_count(in godot_node_path p_self);
|
||||
|
|
@ -508,11 +541,11 @@ namespace Godot.NativeInterop
|
|||
|
||||
// GD, etc
|
||||
|
||||
internal static partial void godotsharp_bytes_to_var(in godot_packed_byte_array p_bytes,
|
||||
internal static partial void godotsharp_bytes_to_var(scoped in godot_packed_byte_array p_bytes,
|
||||
godot_bool p_allow_objects,
|
||||
out godot_variant r_ret);
|
||||
|
||||
internal static partial void godotsharp_convert(in godot_variant p_what, int p_type,
|
||||
internal static partial void godotsharp_convert(scoped in godot_variant p_what, int p_type,
|
||||
out godot_variant r_ret);
|
||||
|
||||
internal static partial int godotsharp_hash(in godot_variant p_var);
|
||||
|
|
@ -549,12 +582,12 @@ namespace Godot.NativeInterop
|
|||
|
||||
internal static partial void godotsharp_weakref(IntPtr p_obj, out godot_ref r_weak_ref);
|
||||
|
||||
internal static partial void godotsharp_str_to_var(in godot_string p_str, out godot_variant r_ret);
|
||||
internal static partial void godotsharp_str_to_var(scoped in godot_string p_str, out godot_variant r_ret);
|
||||
|
||||
internal static partial void godotsharp_var_to_bytes(in godot_variant p_what, godot_bool p_full_objects,
|
||||
internal static partial void godotsharp_var_to_bytes(scoped in godot_variant p_what, godot_bool p_full_objects,
|
||||
out godot_packed_byte_array r_bytes);
|
||||
|
||||
internal static partial void godotsharp_var_to_str(in godot_variant p_var, out godot_string r_ret);
|
||||
internal static partial void godotsharp_var_to_str(scoped in godot_variant p_var, out godot_string r_ret);
|
||||
|
||||
internal static partial void godotsharp_err_print_error(in godot_string p_function, in godot_string p_file, int p_line, in godot_string p_error, in godot_string p_message = default, godot_bool p_editor_notify = godot_bool.False, godot_error_handler_type p_type = godot_error_handler_type.ERR_HANDLER_ERROR);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace Godot.NativeInterop
|
|||
{
|
||||
public static partial class NativeFuncs
|
||||
{
|
||||
public static godot_variant godotsharp_variant_new_copy(in godot_variant src)
|
||||
public static godot_variant godotsharp_variant_new_copy(scoped in godot_variant src)
|
||||
{
|
||||
switch (src.Type)
|
||||
{
|
||||
|
|
@ -48,7 +48,7 @@ namespace Godot.NativeInterop
|
|||
return ret;
|
||||
}
|
||||
|
||||
public static godot_string_name godotsharp_string_name_new_copy(in godot_string_name src)
|
||||
public static godot_string_name godotsharp_string_name_new_copy(scoped in godot_string_name src)
|
||||
{
|
||||
if (src.IsEmpty)
|
||||
return default;
|
||||
|
|
@ -56,7 +56,7 @@ namespace Godot.NativeInterop
|
|||
return ret;
|
||||
}
|
||||
|
||||
public static godot_node_path godotsharp_node_path_new_copy(in godot_node_path src)
|
||||
public static godot_node_path godotsharp_node_path_new_copy(scoped in godot_node_path src)
|
||||
{
|
||||
if (src.IsEmpty)
|
||||
return default;
|
||||
|
|
@ -70,7 +70,7 @@ namespace Godot.NativeInterop
|
|||
return ret;
|
||||
}
|
||||
|
||||
public static godot_array godotsharp_array_new_copy(in godot_array src)
|
||||
public static godot_array godotsharp_array_new_copy(scoped in godot_array src)
|
||||
{
|
||||
godotsharp_array_new_copy(out godot_array ret, src);
|
||||
return ret;
|
||||
|
|
@ -82,7 +82,7 @@ namespace Godot.NativeInterop
|
|||
return ret;
|
||||
}
|
||||
|
||||
public static godot_dictionary godotsharp_dictionary_new_copy(in godot_dictionary src)
|
||||
public static godot_dictionary godotsharp_dictionary_new_copy(scoped in godot_dictionary src)
|
||||
{
|
||||
godotsharp_dictionary_new_copy(out godot_dictionary ret, src);
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -117,137 +117,137 @@ namespace Godot.NativeInterop
|
|||
public static godot_variant CreateFromString(string? from)
|
||||
=> CreateFromStringTakingOwnershipOfDisposableValue(Marshaling.ConvertStringToNative(from));
|
||||
|
||||
public static godot_variant CreateFromPackedByteArray(in godot_packed_byte_array from)
|
||||
public static godot_variant CreateFromPackedByteArray(scoped in godot_packed_byte_array from)
|
||||
{
|
||||
NativeFuncs.godotsharp_variant_new_packed_byte_array(out godot_variant ret, from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static godot_variant CreateFromPackedInt32Array(in godot_packed_int32_array from)
|
||||
public static godot_variant CreateFromPackedInt32Array(scoped in godot_packed_int32_array from)
|
||||
{
|
||||
NativeFuncs.godotsharp_variant_new_packed_int32_array(out godot_variant ret, from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static godot_variant CreateFromPackedInt64Array(in godot_packed_int64_array from)
|
||||
public static godot_variant CreateFromPackedInt64Array(scoped in godot_packed_int64_array from)
|
||||
{
|
||||
NativeFuncs.godotsharp_variant_new_packed_int64_array(out godot_variant ret, from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static godot_variant CreateFromPackedFloat32Array(in godot_packed_float32_array from)
|
||||
public static godot_variant CreateFromPackedFloat32Array(scoped in godot_packed_float32_array from)
|
||||
{
|
||||
NativeFuncs.godotsharp_variant_new_packed_float32_array(out godot_variant ret, from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static godot_variant CreateFromPackedFloat64Array(in godot_packed_float64_array from)
|
||||
public static godot_variant CreateFromPackedFloat64Array(scoped in godot_packed_float64_array from)
|
||||
{
|
||||
NativeFuncs.godotsharp_variant_new_packed_float64_array(out godot_variant ret, from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static godot_variant CreateFromPackedStringArray(in godot_packed_string_array from)
|
||||
public static godot_variant CreateFromPackedStringArray(scoped in godot_packed_string_array from)
|
||||
{
|
||||
NativeFuncs.godotsharp_variant_new_packed_string_array(out godot_variant ret, from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static godot_variant CreateFromPackedVector2Array(in godot_packed_vector2_array from)
|
||||
public static godot_variant CreateFromPackedVector2Array(scoped in godot_packed_vector2_array from)
|
||||
{
|
||||
NativeFuncs.godotsharp_variant_new_packed_vector2_array(out godot_variant ret, from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static godot_variant CreateFromPackedVector3Array(in godot_packed_vector3_array from)
|
||||
public static godot_variant CreateFromPackedVector3Array(scoped in godot_packed_vector3_array from)
|
||||
{
|
||||
NativeFuncs.godotsharp_variant_new_packed_vector3_array(out godot_variant ret, from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static godot_variant CreateFromPackedVector4Array(in godot_packed_vector4_array from)
|
||||
public static godot_variant CreateFromPackedVector4Array(scoped in godot_packed_vector4_array from)
|
||||
{
|
||||
NativeFuncs.godotsharp_variant_new_packed_vector4_array(out godot_variant ret, from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static godot_variant CreateFromPackedColorArray(in godot_packed_color_array from)
|
||||
public static godot_variant CreateFromPackedColorArray(scoped in godot_packed_color_array from)
|
||||
{
|
||||
NativeFuncs.godotsharp_variant_new_packed_color_array(out godot_variant ret, from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static godot_variant CreateFromPackedByteArray(Span<byte> from)
|
||||
public static godot_variant CreateFromPackedByteArray(scoped Span<byte> from)
|
||||
{
|
||||
using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedByteArray(from);
|
||||
return CreateFromPackedByteArray(nativePackedArray);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static godot_variant CreateFromPackedInt32Array(Span<int> from)
|
||||
public static godot_variant CreateFromPackedInt32Array(scoped Span<int> from)
|
||||
{
|
||||
using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedInt32Array(from);
|
||||
return CreateFromPackedInt32Array(nativePackedArray);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static godot_variant CreateFromPackedInt64Array(Span<long> from)
|
||||
public static godot_variant CreateFromPackedInt64Array(scoped Span<long> from)
|
||||
{
|
||||
using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedInt64Array(from);
|
||||
return CreateFromPackedInt64Array(nativePackedArray);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static godot_variant CreateFromPackedFloat32Array(Span<float> from)
|
||||
public static godot_variant CreateFromPackedFloat32Array(scoped Span<float> from)
|
||||
{
|
||||
using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedFloat32Array(from);
|
||||
return CreateFromPackedFloat32Array(nativePackedArray);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static godot_variant CreateFromPackedFloat64Array(Span<double> from)
|
||||
public static godot_variant CreateFromPackedFloat64Array(scoped Span<double> from)
|
||||
{
|
||||
using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedFloat64Array(from);
|
||||
return CreateFromPackedFloat64Array(nativePackedArray);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static godot_variant CreateFromPackedStringArray(Span<string> from)
|
||||
public static godot_variant CreateFromPackedStringArray(scoped Span<string> from)
|
||||
{
|
||||
using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedStringArray(from);
|
||||
return CreateFromPackedStringArray(nativePackedArray);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static godot_variant CreateFromPackedVector2Array(Span<Vector2> from)
|
||||
public static godot_variant CreateFromPackedVector2Array(scoped Span<Vector2> from)
|
||||
{
|
||||
using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedVector2Array(from);
|
||||
return CreateFromPackedVector2Array(nativePackedArray);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static godot_variant CreateFromPackedVector3Array(Span<Vector3> from)
|
||||
public static godot_variant CreateFromPackedVector3Array(scoped Span<Vector3> from)
|
||||
{
|
||||
using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedVector3Array(from);
|
||||
return CreateFromPackedVector3Array(nativePackedArray);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static godot_variant CreateFromPackedVector4Array(Span<Vector4> from)
|
||||
public static godot_variant CreateFromPackedVector4Array(scoped Span<Vector4> from)
|
||||
{
|
||||
using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedVector4Array(from);
|
||||
return CreateFromPackedVector4Array(nativePackedArray);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static godot_variant CreateFromPackedColorArray(Span<Color> from)
|
||||
public static godot_variant CreateFromPackedColorArray(scoped Span<Color> from)
|
||||
{
|
||||
using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedColorArray(from);
|
||||
return CreateFromPackedColorArray(nativePackedArray);
|
||||
}
|
||||
|
||||
public static godot_variant CreateFromSystemArrayOfStringName(Span<StringName> from)
|
||||
public static godot_variant CreateFromSystemArrayOfStringName(scoped Span<StringName> from)
|
||||
{
|
||||
if (from == null)
|
||||
return default;
|
||||
|
|
@ -255,7 +255,7 @@ namespace Godot.NativeInterop
|
|||
return CreateFromArray((godot_array)fromGodot.NativeValue);
|
||||
}
|
||||
|
||||
public static godot_variant CreateFromSystemArrayOfNodePath(Span<NodePath> from)
|
||||
public static godot_variant CreateFromSystemArrayOfNodePath(scoped Span<NodePath> from)
|
||||
{
|
||||
if (from == null)
|
||||
return default;
|
||||
|
|
@ -263,7 +263,7 @@ namespace Godot.NativeInterop
|
|||
return CreateFromArray((godot_array)fromGodot.NativeValue);
|
||||
}
|
||||
|
||||
public static godot_variant CreateFromSystemArrayOfRid(Span<Rid> from)
|
||||
public static godot_variant CreateFromSystemArrayOfRid(scoped Span<Rid> from)
|
||||
{
|
||||
if (from == null)
|
||||
return default;
|
||||
|
|
@ -279,7 +279,7 @@ namespace Godot.NativeInterop
|
|||
return CreateFromArray((godot_array)fromGodot.NativeValue);
|
||||
}
|
||||
|
||||
public static godot_variant CreateFromArray(godot_array from)
|
||||
public static godot_variant CreateFromArray(scoped in godot_array from)
|
||||
{
|
||||
NativeFuncs.godotsharp_variant_new_array(out godot_variant ret, from);
|
||||
return ret;
|
||||
|
|
@ -293,7 +293,7 @@ namespace Godot.NativeInterop
|
|||
public static godot_variant CreateFromArray<[MustBeVariant] T>(Array<T>? from)
|
||||
=> from != null ? CreateFromArray((godot_array)((Collections.Array)from).NativeValue) : default;
|
||||
|
||||
public static godot_variant CreateFromDictionary(godot_dictionary from)
|
||||
public static godot_variant CreateFromDictionary(scoped in godot_dictionary from)
|
||||
{
|
||||
NativeFuncs.godotsharp_variant_new_dictionary(out godot_variant ret, from);
|
||||
return ret;
|
||||
|
|
@ -307,7 +307,7 @@ namespace Godot.NativeInterop
|
|||
public static godot_variant CreateFromDictionary<[MustBeVariant] TKey, [MustBeVariant] TValue>(Dictionary<TKey, TValue>? from)
|
||||
=> from != null ? CreateFromDictionary((godot_dictionary)((Dictionary)from).NativeValue) : default;
|
||||
|
||||
public static godot_variant CreateFromStringName(godot_string_name from)
|
||||
public static godot_variant CreateFromStringName(scoped in godot_string_name from)
|
||||
{
|
||||
NativeFuncs.godotsharp_variant_new_string_name(out godot_variant ret, from);
|
||||
return ret;
|
||||
|
|
@ -317,7 +317,7 @@ namespace Godot.NativeInterop
|
|||
public static godot_variant CreateFromStringName(StringName? from)
|
||||
=> from != null ? CreateFromStringName((godot_string_name)from.NativeValue) : default;
|
||||
|
||||
public static godot_variant CreateFromNodePath(godot_node_path from)
|
||||
public static godot_variant CreateFromNodePath(scoped in godot_node_path from)
|
||||
{
|
||||
NativeFuncs.godotsharp_variant_new_node_path(out godot_variant ret, from);
|
||||
return ret;
|
||||
|
|
@ -510,7 +510,7 @@ namespace Godot.NativeInterop
|
|||
}
|
||||
}
|
||||
|
||||
public static godot_string_name ConvertToNativeStringName(in godot_variant p_var)
|
||||
public static godot_string_name ConvertToNativeStringName(scoped in godot_variant p_var)
|
||||
=> p_var.Type == Variant.Type.StringName ?
|
||||
NativeFuncs.godotsharp_string_name_new_copy(p_var.StringName) :
|
||||
NativeFuncs.godotsharp_variant_as_string_name(p_var);
|
||||
|
|
@ -519,7 +519,7 @@ namespace Godot.NativeInterop
|
|||
public static StringName ConvertToStringName(in godot_variant p_var)
|
||||
=> StringName.CreateTakingOwnershipOfDisposableValue(ConvertToNativeStringName(p_var));
|
||||
|
||||
public static godot_node_path ConvertToNativeNodePath(in godot_variant p_var)
|
||||
public static godot_node_path ConvertToNativeNodePath(scoped in godot_variant p_var)
|
||||
=> p_var.Type == Variant.Type.NodePath ?
|
||||
NativeFuncs.godotsharp_node_path_new_copy(p_var.NodePath) :
|
||||
NativeFuncs.godotsharp_variant_as_node_path(p_var);
|
||||
|
|
@ -529,22 +529,28 @@ namespace Godot.NativeInterop
|
|||
=> NodePath.CreateTakingOwnershipOfDisposableValue(ConvertToNativeNodePath(p_var));
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static godot_callable ConvertToNativeCallable(in godot_variant p_var)
|
||||
public static godot_callable ConvertToNativeCallable(scoped in godot_variant p_var)
|
||||
=> NativeFuncs.godotsharp_variant_as_callable(p_var);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Callable ConvertToCallable(in godot_variant p_var)
|
||||
=> Marshaling.ConvertCallableToManaged(ConvertToNativeCallable(p_var));
|
||||
{
|
||||
using var callable = ConvertToNativeCallable(p_var);
|
||||
return Marshaling.ConvertCallableToManaged(callable);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static godot_signal ConvertToNativeSignal(in godot_variant p_var)
|
||||
public static godot_signal ConvertToNativeSignal(scoped in godot_variant p_var)
|
||||
=> NativeFuncs.godotsharp_variant_as_signal(p_var);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Signal ConvertToSignal(in godot_variant p_var)
|
||||
=> Marshaling.ConvertSignalToManaged(ConvertToNativeSignal(p_var));
|
||||
{
|
||||
using var signal = ConvertToNativeSignal(p_var);
|
||||
return Marshaling.ConvertSignalToManaged(signal);
|
||||
}
|
||||
|
||||
public static godot_array ConvertToNativeArray(in godot_variant p_var)
|
||||
public static godot_array ConvertToNativeArray(scoped in godot_variant p_var)
|
||||
=> p_var.Type == Variant.Type.Array ?
|
||||
NativeFuncs.godotsharp_array_new_copy(p_var.Array) :
|
||||
NativeFuncs.godotsharp_variant_as_array(p_var);
|
||||
|
|
@ -557,7 +563,7 @@ namespace Godot.NativeInterop
|
|||
public static Array<T> ConvertToArray<[MustBeVariant] T>(in godot_variant p_var)
|
||||
=> Array<T>.CreateTakingOwnershipOfDisposableValue(ConvertToNativeArray(p_var));
|
||||
|
||||
public static godot_dictionary ConvertToNativeDictionary(in godot_variant p_var)
|
||||
public static godot_dictionary ConvertToNativeDictionary(scoped in godot_variant p_var)
|
||||
=> p_var.Type == Variant.Type.Dictionary ?
|
||||
NativeFuncs.godotsharp_dictionary_new_copy(p_var.Dictionary) :
|
||||
NativeFuncs.godotsharp_variant_as_dictionary(p_var);
|
||||
|
|
|
|||
|
|
@ -7,22 +7,23 @@ namespace Godot.NativeInterop;
|
|||
|
||||
public partial class VariantUtils
|
||||
{
|
||||
private static Exception UnsupportedType<T>() => new InvalidOperationException(
|
||||
private static InvalidOperationException UnsupportedType<T>() => new InvalidOperationException(
|
||||
$"The type is not supported for conversion to/from Variant: '{typeof(T).FullName}'");
|
||||
|
||||
internal static class GenericConversion<T>
|
||||
{
|
||||
public static unsafe godot_variant ToVariant(in T from) =>
|
||||
ToVariantCb != null ? ToVariantCb(from) : throw UnsupportedType<T>();
|
||||
internal delegate godot_variant ToVariantConverter(scoped in T from);
|
||||
internal delegate T FromVariantConverter(in godot_variant from);
|
||||
|
||||
public static unsafe godot_variant ToVariant(scoped in T from) =>
|
||||
ToVariantCb != null ? ToVariantCb(from) : throw UnsupportedType<T>();
|
||||
|
||||
public static unsafe T FromVariant(in godot_variant variant) =>
|
||||
FromVariantCb != null ? FromVariantCb(variant) : throw UnsupportedType<T>();
|
||||
|
||||
// ReSharper disable once StaticMemberInGenericType
|
||||
internal static unsafe delegate*<in T, godot_variant> ToVariantCb;
|
||||
internal static ToVariantConverter? ToVariantCb;
|
||||
|
||||
// ReSharper disable once StaticMemberInGenericType
|
||||
internal static unsafe delegate*<in godot_variant, T> FromVariantCb;
|
||||
internal static FromVariantConverter? FromVariantCb;
|
||||
|
||||
static GenericConversion()
|
||||
{
|
||||
|
|
@ -31,10 +32,10 @@ public partial class VariantUtils
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static godot_variant CreateFrom<[MustBeVariant] T>(in T from)
|
||||
public static godot_variant CreateFrom<[MustBeVariant] T>(scoped in T from)
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static TTo UnsafeAs<TTo>(in T f) => Unsafe.As<T, TTo>(ref Unsafe.AsRef(f));
|
||||
static TTo UnsafeAs<TTo>(in T f) => Unsafe.As<T, TTo>(ref Unsafe.AsRef(in f));
|
||||
|
||||
// `typeof(T) == typeof(X)` is optimized away. We cannot cache `typeof(T)` in a local variable, as it's not optimized when done like that.
|
||||
|
||||
|
|
@ -227,7 +228,7 @@ public partial class VariantUtils
|
|||
public static T ConvertTo<[MustBeVariant] T>(in godot_variant variant)
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
static T UnsafeAsT<TFrom>(TFrom f) => Unsafe.As<TFrom, T>(ref Unsafe.AsRef(f));
|
||||
static T UnsafeAsT<TFrom>(TFrom f) => Unsafe.As<TFrom, T>(ref Unsafe.AsRef(in f));
|
||||
|
||||
if (typeof(T) == typeof(bool))
|
||||
return UnsafeAsT(ConvertToBool(variant));
|
||||
|
|
|
|||
|
|
@ -171,6 +171,26 @@ namespace Godot
|
|||
return _position + (_size * 0.5f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the support point in a given direction.
|
||||
/// This is useful for collision detection algorithms.
|
||||
/// </summary>
|
||||
/// <param name="direction">The direction to find support for.</param>
|
||||
/// <returns>A vector representing the support.</returns>
|
||||
public readonly Vector2 GetSupport(Vector2 direction)
|
||||
{
|
||||
Vector2 support = _position;
|
||||
if (direction.X > 0.0f)
|
||||
{
|
||||
support.X += _size.X;
|
||||
}
|
||||
if (direction.Y > 0.0f)
|
||||
{
|
||||
support.Y += _size.Y;
|
||||
}
|
||||
return support;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a copy of the <see cref="Rect2"/> grown by the specified amount
|
||||
/// on all sides.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
#nullable enable
|
||||
|
||||
|
|
@ -7,10 +10,186 @@ namespace Godot;
|
|||
|
||||
internal class ReflectionUtils
|
||||
{
|
||||
private static readonly HashSet<Type>? _tupleTypeSet;
|
||||
private static readonly Dictionary<Type, string>? _builtinTypeNameDictionary;
|
||||
internal static readonly bool IsEditorHintCached;
|
||||
|
||||
static ReflectionUtils()
|
||||
{
|
||||
IsEditorHintCached = Engine.IsEditorHint();
|
||||
if (!IsEditorHintCached)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_tupleTypeSet = new HashSet<Type>
|
||||
{
|
||||
// ValueTuple with only one element should be treated as normal generic type.
|
||||
//typeof(ValueTuple<>),
|
||||
typeof(ValueTuple<,>),
|
||||
typeof(ValueTuple<,,>),
|
||||
typeof(ValueTuple<,,,>),
|
||||
typeof(ValueTuple<,,,,>),
|
||||
typeof(ValueTuple<,,,,,>),
|
||||
typeof(ValueTuple<,,,,,,>),
|
||||
typeof(ValueTuple<,,,,,,,>),
|
||||
};
|
||||
|
||||
_builtinTypeNameDictionary ??= new Dictionary<Type, string>
|
||||
{
|
||||
{ typeof(sbyte), "sbyte" },
|
||||
{ typeof(byte), "byte" },
|
||||
{ typeof(short), "short" },
|
||||
{ typeof(ushort), "ushort" },
|
||||
{ typeof(int), "int" },
|
||||
{ typeof(uint), "uint" },
|
||||
{ typeof(long), "long" },
|
||||
{ typeof(ulong), "ulong" },
|
||||
{ typeof(nint), "nint" },
|
||||
{ typeof(nuint), "nuint" },
|
||||
{ typeof(float), "float" },
|
||||
{ typeof(double), "double" },
|
||||
{ typeof(decimal), "decimal" },
|
||||
{ typeof(bool), "bool" },
|
||||
{ typeof(char), "char" },
|
||||
{ typeof(string), "string" },
|
||||
{ typeof(object), "object" },
|
||||
};
|
||||
}
|
||||
|
||||
public static Type? FindTypeInLoadedAssemblies(string assemblyName, string typeFullName)
|
||||
{
|
||||
return AppDomain.CurrentDomain.GetAssemblies()
|
||||
.FirstOrDefault(a => a.GetName().Name == assemblyName)?
|
||||
.GetType(typeFullName);
|
||||
}
|
||||
|
||||
public static string ConstructTypeName(Type type)
|
||||
{
|
||||
if (!IsEditorHintCached)
|
||||
{
|
||||
return type.Name;
|
||||
}
|
||||
|
||||
if (type is { IsArray: false, IsGenericType: false })
|
||||
{
|
||||
return GetSimpleTypeName(type);
|
||||
}
|
||||
|
||||
var typeNameBuilder = new StringBuilder();
|
||||
AppendType(typeNameBuilder, type);
|
||||
return typeNameBuilder.ToString();
|
||||
|
||||
static void AppendType(StringBuilder sb, Type type)
|
||||
{
|
||||
if (type.IsArray)
|
||||
{
|
||||
AppendArray(sb, type);
|
||||
}
|
||||
else if (type.IsGenericType)
|
||||
{
|
||||
AppendGeneric(sb, type);
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(GetSimpleTypeName(type));
|
||||
}
|
||||
}
|
||||
|
||||
static void AppendArray(StringBuilder sb, Type type)
|
||||
{
|
||||
// Append inner most non-array element.
|
||||
var elementType = type.GetElementType()!;
|
||||
while (elementType.IsArray)
|
||||
{
|
||||
elementType = elementType.GetElementType()!;
|
||||
}
|
||||
|
||||
AppendType(sb, elementType);
|
||||
// Append brackets.
|
||||
AppendArrayBrackets(sb, type);
|
||||
|
||||
static void AppendArrayBrackets(StringBuilder sb, Type? type)
|
||||
{
|
||||
while (type != null && type.IsArray)
|
||||
{
|
||||
int rank = type.GetArrayRank();
|
||||
sb.Append('[');
|
||||
sb.Append(',', rank - 1);
|
||||
sb.Append(']');
|
||||
type = type.GetElementType();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void AppendGeneric(StringBuilder sb, Type type)
|
||||
{
|
||||
var genericArgs = type.GenericTypeArguments;
|
||||
var genericDefinition = type.GetGenericTypeDefinition();
|
||||
|
||||
// Nullable<T>
|
||||
if (genericDefinition == typeof(Nullable<>))
|
||||
{
|
||||
AppendType(sb, genericArgs[0]);
|
||||
sb.Append('?');
|
||||
return;
|
||||
}
|
||||
|
||||
// ValueTuple
|
||||
Debug.Assert(_tupleTypeSet != null);
|
||||
if (_tupleTypeSet.Contains(genericDefinition))
|
||||
{
|
||||
sb.Append('(');
|
||||
while (true)
|
||||
{
|
||||
// We assume that ValueTuple has 1~8 elements.
|
||||
// And the 8th element (TRest) is always another ValueTuple.
|
||||
|
||||
// This is a hard coded tuple element length check.
|
||||
if (genericArgs.Length != 8)
|
||||
{
|
||||
AppendParamTypes(sb, genericArgs);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
AppendParamTypes(sb, genericArgs.AsSpan(0, 7));
|
||||
sb.Append(", ");
|
||||
|
||||
// TRest should be a ValueTuple!
|
||||
var nextTuple = genericArgs[7];
|
||||
|
||||
genericArgs = nextTuple.GenericTypeArguments;
|
||||
}
|
||||
}
|
||||
sb.Append(')');
|
||||
return;
|
||||
}
|
||||
|
||||
// Normal generic
|
||||
var typeName = type.Name.AsSpan();
|
||||
sb.Append(typeName[..typeName.LastIndexOf('`')]);
|
||||
sb.Append('<');
|
||||
AppendParamTypes(sb, genericArgs);
|
||||
sb.Append('>');
|
||||
|
||||
static void AppendParamTypes(StringBuilder sb, ReadOnlySpan<Type> genericArgs)
|
||||
{
|
||||
int n = genericArgs.Length - 1;
|
||||
for (int i = 0; i < n; i += 1)
|
||||
{
|
||||
AppendType(sb, genericArgs[i]);
|
||||
sb.Append(", ");
|
||||
}
|
||||
|
||||
AppendType(sb, genericArgs[n]);
|
||||
}
|
||||
}
|
||||
|
||||
static string GetSimpleTypeName(Type type)
|
||||
{
|
||||
Debug.Assert(_builtinTypeNameDictionary != null);
|
||||
return _builtinTypeNameDictionary.TryGetValue(type, out string? name) ? name : type.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -979,7 +979,7 @@ namespace Godot
|
|||
{
|
||||
if (instance.Length < 3)
|
||||
return false;
|
||||
if (instance[from] != '0' || instance[from + 1] != 'x')
|
||||
if (instance[from] != '0' || instance[from + 1] != 'x' || instance[from + 1] != 'X')
|
||||
return false;
|
||||
from += 2;
|
||||
}
|
||||
|
|
@ -1581,7 +1581,7 @@ namespace Godot
|
|||
if (end < 0)
|
||||
end = len;
|
||||
if (allowEmpty || end > from)
|
||||
ret.Add(float.Parse(instance.Substring(from), CultureInfo.InvariantCulture));
|
||||
ret.Add(float.Parse(instance.AsSpan(from), CultureInfo.InvariantCulture));
|
||||
if (end == len)
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ namespace Godot
|
|||
{
|
||||
get
|
||||
{
|
||||
real_t detSign = Mathf.Sign(BasisDeterminant());
|
||||
real_t detSign = Mathf.Sign(Determinant());
|
||||
return new Vector2(X.Length(), detSign * Y.Length());
|
||||
}
|
||||
}
|
||||
|
|
@ -59,7 +59,7 @@ namespace Godot
|
|||
{
|
||||
get
|
||||
{
|
||||
real_t detSign = Mathf.Sign(BasisDeterminant());
|
||||
real_t detSign = Mathf.Sign(Determinant());
|
||||
return Mathf.Acos(X.Normalized().Dot(detSign * Y.Normalized())) - Mathf.Pi * 0.5f;
|
||||
}
|
||||
}
|
||||
|
|
@ -135,7 +135,7 @@ namespace Godot
|
|||
/// <returns>The inverse transformation matrix.</returns>
|
||||
public readonly Transform2D AffineInverse()
|
||||
{
|
||||
real_t det = BasisDeterminant();
|
||||
real_t det = Determinant();
|
||||
|
||||
if (det == 0)
|
||||
throw new InvalidOperationException("Matrix determinant is zero and cannot be inverted.");
|
||||
|
|
@ -157,15 +157,16 @@ namespace Godot
|
|||
|
||||
/// <summary>
|
||||
/// Returns the determinant of the basis matrix. If the basis is
|
||||
/// uniformly scaled, its determinant is the square of the scale.
|
||||
/// uniformly scaled, then its determinant equals the square of the
|
||||
/// scale factor.
|
||||
///
|
||||
/// A negative determinant means the Y scale is negative.
|
||||
/// A zero determinant means the basis isn't invertible,
|
||||
/// and is usually considered invalid.
|
||||
/// A negative determinant means the basis was flipped, so one part of
|
||||
/// the scale is negative. A zero determinant means the basis isn't
|
||||
/// invertible, and is usually considered invalid.
|
||||
/// </summary>
|
||||
/// <returns>The determinant of the basis matrix.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private readonly real_t BasisDeterminant()
|
||||
public readonly real_t Determinant()
|
||||
{
|
||||
return (X.X * Y.Y) - (X.Y * Y.X);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -468,8 +468,8 @@ namespace Godot
|
|||
{
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
real_t e = transform.Basis[i][j] * min[j];
|
||||
real_t f = transform.Basis[i][j] * max[j];
|
||||
real_t e = transform.Basis[j][i] * min[j];
|
||||
real_t f = transform.Basis[j][i] * max[j];
|
||||
if (e < f)
|
||||
{
|
||||
tmin[i] += e;
|
||||
|
|
|
|||
|
|
@ -692,10 +692,18 @@ namespace Godot
|
|||
// Zero length vectors have no angle, so the best we can do is either lerp or throw an error.
|
||||
return Lerp(to, weight);
|
||||
}
|
||||
Vector3 axis = Cross(to);
|
||||
real_t axisLengthSquared = axis.LengthSquared();
|
||||
if (axisLengthSquared == 0.0)
|
||||
{
|
||||
// Colinear vectors have no rotation axis or angle between them, so the best we can do is lerp.
|
||||
return Lerp(to, weight);
|
||||
}
|
||||
axis /= Mathf.Sqrt(axisLengthSquared);
|
||||
real_t startLength = Mathf.Sqrt(startLengthSquared);
|
||||
real_t resultLength = Mathf.Lerp(startLength, Mathf.Sqrt(endLengthSquared), weight);
|
||||
real_t angle = AngleTo(to);
|
||||
return Rotated(Cross(to).Normalized(), angle * weight) * (resultLength / startLength);
|
||||
return Rotated(axis, angle * weight) * (resultLength / startLength);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -1,23 +1,25 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{AEBF0036-DA76-4341-B651-A3F2856AB2FA}</ProjectGuid>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
<OutputPath>bin/$(Configuration)</OutputPath>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<RootNamespace>Godot</RootNamespace>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<DocumentationFile>$(OutputPath)/$(AssemblyName).xml</DocumentationFile>
|
||||
<EnableDefaultItems>false</EnableDefaultItems>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<LangVersion>10</LangVersion>
|
||||
|
||||
<AnalysisMode>Recommended</AnalysisMode>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>Godot C# Core API.</Description>
|
||||
<Authors>Godot Engine contributors</Authors>
|
||||
|
||||
<PackageId>GodotSharp</PackageId>
|
||||
<Version>4.3.0</Version>
|
||||
<Version>4.4.0</Version>
|
||||
<PackageVersion>$(PackageVersion_GodotSharp)</PackageVersion>
|
||||
<RepositoryUrl>https://github.com/godotengine/godot/tree/master/modules/mono/glue/GodotSharp/GodotSharp</RepositoryUrl>
|
||||
<PackageProjectUrl>$(RepositoryUrl)</PackageProjectUrl>
|
||||
|
|
@ -28,26 +30,32 @@
|
|||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- SdkPackageVersions.props for easy access -->
|
||||
<None Include="$(GodotSdkPackageVersionsFilePath)">
|
||||
<Link>SdkPackageVersions.props</Link>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<DefineConstants>$(DefineConstants);GODOT</DefineConstants>
|
||||
<DefineConstants Condition=" '$(GodotFloat64)' == 'true' ">REAL_T_IS_DOUBLE;$(DefineConstants)</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ReflectionAnalyzers" Version="0.1.22-dev" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers" />
|
||||
<!--PackageReference Include="IDisposableAnalyzers" Version="3.4.13" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers" /-->
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Godot.SourceGenerators.Internal\Godot.SourceGenerators.Internal.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Sources -->
|
||||
<ItemGroup>
|
||||
<Compile Include="Core\Aabb.cs" />
|
||||
<Compile Include="Core\Attributes\ExportToolButtonAttribute.cs" />
|
||||
<Compile Include="Core\Bridge\GodotSerializationInfo.cs" />
|
||||
<Compile Include="Core\Bridge\MethodInfo.cs" />
|
||||
<Compile Include="Core\Callable.generics.cs" />
|
||||
|
|
@ -134,10 +142,12 @@
|
|||
<Compile Include="GlobalUsings.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Compat Sources -->
|
||||
<ItemGroup>
|
||||
<ItemGroup Condition=" '$(GodotNoDeprecated)' == '' ">
|
||||
<Compile Include="Compat.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<!--
|
||||
We import a props file with auto-generated includes. This works well with Rider.
|
||||
However, Visual Studio and MonoDevelop won't list them in the solution explorer.
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{8FBEC238-D944-4074-8548-B3B524305905}</ProjectGuid>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
<OutputPath>bin/$(Configuration)</OutputPath>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<RootNamespace>Godot</RootNamespace>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<DocumentationFile>$(OutputPath)/$(AssemblyName).xml</DocumentationFile>
|
||||
<EnableDefaultItems>false</EnableDefaultItems>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<LangVersion>10</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<Description>Godot C# Editor API.</Description>
|
||||
<Authors>Godot Engine contributors</Authors>
|
||||
|
||||
<PackageId>GodotSharpEditor</PackageId>
|
||||
<Version>4.3.0</Version>
|
||||
<Version>4.4.0</Version>
|
||||
<PackageVersion>$(PackageVersion_GodotSharp)</PackageVersion>
|
||||
<RepositoryUrl>https://github.com/godotengine/godot/tree/master/modules/mono/glue/GodotSharp/GodotSharpEditor</RepositoryUrl>
|
||||
<PackageProjectUrl>$(RepositoryUrl)</PackageProjectUrl>
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<!-- Compat Sources -->
|
||||
<ItemGroup>
|
||||
<ItemGroup Condition=" '$(GodotNoDeprecated)' == '' ">
|
||||
<Compile Include="Compat.cs" />
|
||||
</ItemGroup>
|
||||
<!--
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ extern "C" {
|
|||
// For ArrayPrivate and DictionaryPrivate
|
||||
static_assert(sizeof(SafeRefCount) == sizeof(uint32_t));
|
||||
|
||||
typedef Object *(*godotsharp_class_creation_func)();
|
||||
typedef Object *(*godotsharp_class_creation_func)(bool);
|
||||
|
||||
bool godotsharp_dotnet_module_is_initialized() {
|
||||
return GDMono::get_singleton()->is_initialized();
|
||||
|
|
@ -559,6 +559,18 @@ godot_color godotsharp_color_from_ok_hsl(float p_h, float p_s, float p_l, float
|
|||
return ret;
|
||||
}
|
||||
|
||||
float godotsharp_color_get_ok_hsl_h(const Color *p_self) {
|
||||
return p_self->get_ok_hsl_h();
|
||||
}
|
||||
|
||||
float godotsharp_color_get_ok_hsl_s(const Color *p_self) {
|
||||
return p_self->get_ok_hsl_s();
|
||||
}
|
||||
|
||||
float godotsharp_color_get_ok_hsl_l(const Color *p_self) {
|
||||
return p_self->get_ok_hsl_l();
|
||||
}
|
||||
|
||||
// GDNative functions
|
||||
|
||||
// gdnative.h
|
||||
|
|
@ -1098,6 +1110,20 @@ void godotsharp_array_make_read_only(Array *p_self) {
|
|||
p_self->make_read_only();
|
||||
}
|
||||
|
||||
void godotsharp_array_set_typed(Array *p_self, uint32_t p_elem_type, const StringName *p_elem_class_name, const Ref<CSharpScript> *p_elem_script) {
|
||||
Variant elem_script_variant;
|
||||
StringName elem_class_name = *p_elem_class_name;
|
||||
if (p_elem_script && p_elem_script->is_valid()) {
|
||||
elem_script_variant = Variant(p_elem_script->ptr());
|
||||
elem_class_name = p_elem_script->ptr()->get_instance_base_type();
|
||||
}
|
||||
p_self->set_typed(p_elem_type, elem_class_name, p_elem_script->ptr());
|
||||
}
|
||||
|
||||
bool godotsharp_array_is_typed(const Array *p_self) {
|
||||
return p_self->is_typed();
|
||||
}
|
||||
|
||||
void godotsharp_array_max(const Array *p_self, Variant *r_value) {
|
||||
*r_value = p_self->max();
|
||||
}
|
||||
|
|
@ -1207,6 +1233,54 @@ void godotsharp_dictionary_make_read_only(Dictionary *p_self) {
|
|||
p_self->make_read_only();
|
||||
}
|
||||
|
||||
void godotsharp_dictionary_set_typed(Dictionary *p_self, uint32_t p_key_type, const StringName *p_key_class_name, const Ref<CSharpScript> *p_key_script, uint32_t p_value_type, const StringName *p_value_class_name, const Ref<CSharpScript> *p_value_script) {
|
||||
Variant key_script_variant;
|
||||
StringName key_class_name = *p_key_class_name;
|
||||
if (p_key_script && p_key_script->is_valid()) {
|
||||
key_script_variant = Variant(p_key_script->ptr());
|
||||
key_class_name = p_key_script->ptr()->get_instance_base_type();
|
||||
}
|
||||
Variant value_script_variant;
|
||||
StringName value_class_name = *p_value_class_name;
|
||||
if (p_value_script && p_value_script->is_valid()) {
|
||||
value_script_variant = Variant(p_value_script->ptr());
|
||||
value_class_name = p_value_script->ptr()->get_instance_base_type();
|
||||
}
|
||||
p_self->set_typed(p_key_type, key_class_name, p_key_script->ptr(), p_value_type, value_class_name, p_value_script->ptr());
|
||||
}
|
||||
|
||||
bool godotsharp_dictionary_is_typed_key(const Dictionary *p_self) {
|
||||
return p_self->is_typed_key();
|
||||
}
|
||||
|
||||
bool godotsharp_dictionary_is_typed_value(const Dictionary *p_self) {
|
||||
return p_self->is_typed_value();
|
||||
}
|
||||
|
||||
uint32_t godotsharp_dictionary_get_typed_key_builtin(const Dictionary *p_self) {
|
||||
return p_self->get_typed_key_builtin();
|
||||
}
|
||||
|
||||
uint32_t godotsharp_dictionary_get_typed_value_builtin(const Dictionary *p_self) {
|
||||
return p_self->get_typed_value_builtin();
|
||||
}
|
||||
|
||||
void godotsharp_dictionary_get_typed_key_class_name(const Dictionary *p_self, StringName *r_dest) {
|
||||
memnew_placement(r_dest, StringName(p_self->get_typed_key_class_name()));
|
||||
}
|
||||
|
||||
void godotsharp_dictionary_get_typed_value_class_name(const Dictionary *p_self, StringName *r_dest) {
|
||||
memnew_placement(r_dest, StringName(p_self->get_typed_value_class_name()));
|
||||
}
|
||||
|
||||
void godotsharp_dictionary_get_typed_key_script(const Dictionary *p_self, Variant *r_dest) {
|
||||
memnew_placement(r_dest, Variant(p_self->get_typed_key_script()));
|
||||
}
|
||||
|
||||
void godotsharp_dictionary_get_typed_value_script(const Dictionary *p_self, Variant *r_dest) {
|
||||
memnew_placement(r_dest, Variant(p_self->get_typed_value_script()));
|
||||
}
|
||||
|
||||
void godotsharp_dictionary_to_string(const Dictionary *p_self, String *r_str) {
|
||||
*r_str = Variant(*p_self).operator String();
|
||||
}
|
||||
|
|
@ -1311,7 +1385,7 @@ void godotsharp_weakref(Object *p_ptr, Ref<RefCounted> *r_weak_ref) {
|
|||
|
||||
if (rc) {
|
||||
Ref<RefCounted> r = rc;
|
||||
if (!r.is_valid()) {
|
||||
if (r.is_null()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1489,6 +1563,9 @@ static const void *unmanaged_callbacks[]{
|
|||
(void *)godotsharp_callable_call,
|
||||
(void *)godotsharp_callable_call_deferred,
|
||||
(void *)godotsharp_color_from_ok_hsl,
|
||||
(void *)godotsharp_color_get_ok_hsl_h,
|
||||
(void *)godotsharp_color_get_ok_hsl_s,
|
||||
(void *)godotsharp_color_get_ok_hsl_l,
|
||||
(void *)godotsharp_method_bind_ptrcall,
|
||||
(void *)godotsharp_method_bind_call,
|
||||
(void *)godotsharp_variant_new_string_name,
|
||||
|
|
@ -1585,6 +1662,8 @@ static const void *unmanaged_callbacks[]{
|
|||
(void *)godotsharp_array_insert,
|
||||
(void *)godotsharp_array_last_index_of,
|
||||
(void *)godotsharp_array_make_read_only,
|
||||
(void *)godotsharp_array_set_typed,
|
||||
(void *)godotsharp_array_is_typed,
|
||||
(void *)godotsharp_array_max,
|
||||
(void *)godotsharp_array_min,
|
||||
(void *)godotsharp_array_pick_random,
|
||||
|
|
@ -1610,6 +1689,15 @@ static const void *unmanaged_callbacks[]{
|
|||
(void *)godotsharp_dictionary_recursive_equal,
|
||||
(void *)godotsharp_dictionary_remove_key,
|
||||
(void *)godotsharp_dictionary_make_read_only,
|
||||
(void *)godotsharp_dictionary_set_typed,
|
||||
(void *)godotsharp_dictionary_is_typed_key,
|
||||
(void *)godotsharp_dictionary_is_typed_value,
|
||||
(void *)godotsharp_dictionary_get_typed_key_builtin,
|
||||
(void *)godotsharp_dictionary_get_typed_value_builtin,
|
||||
(void *)godotsharp_dictionary_get_typed_key_class_name,
|
||||
(void *)godotsharp_dictionary_get_typed_value_class_name,
|
||||
(void *)godotsharp_dictionary_get_typed_key_script,
|
||||
(void *)godotsharp_dictionary_get_typed_value_script,
|
||||
(void *)godotsharp_dictionary_to_string,
|
||||
(void *)godotsharp_string_simplify_path,
|
||||
(void *)godotsharp_string_to_camel_case,
|
||||
|
|
|
|||
|
|
@ -192,9 +192,15 @@ private:
|
|||
}
|
||||
}
|
||||
if (!has_data) {
|
||||
// 3. Extract the data to a temporary location to load from there.
|
||||
Ref<DirAccess> da = DirAccess::create_for_path(packed_path);
|
||||
ERR_FAIL_NULL(da);
|
||||
// 3. Extract the data to a temporary location to load from there, delete old data if it exists but is not up-to-date.
|
||||
Ref<DirAccess> da;
|
||||
if (DirAccess::exists(data_dir_root)) {
|
||||
da = DirAccess::open(data_dir_root);
|
||||
ERR_FAIL_COND(da.is_null());
|
||||
ERR_FAIL_COND(da->erase_contents_recursive() != OK);
|
||||
}
|
||||
da = DirAccess::create_for_path(packed_path);
|
||||
ERR_FAIL_COND(da.is_null());
|
||||
ERR_FAIL_COND(da->copy_dir(packed_path, data_dir_root) != OK);
|
||||
}
|
||||
api_assemblies_dir = data_dir_root;
|
||||
|
|
|
|||
|
|
@ -61,6 +61,14 @@ hostfxr_initialize_for_runtime_config_fn hostfxr_initialize_for_runtime_config =
|
|||
hostfxr_get_runtime_delegate_fn hostfxr_get_runtime_delegate = nullptr;
|
||||
hostfxr_close_fn hostfxr_close = nullptr;
|
||||
|
||||
#ifndef TOOLS_ENABLED
|
||||
typedef int(CORECLR_DELEGATE_CALLTYPE *coreclr_create_delegate_fn)(void *hostHandle, unsigned int domainId, const char *entryPointAssemblyName, const char *entryPointTypeName, const char *entryPointMethodName, void **delegate);
|
||||
typedef int(CORECLR_DELEGATE_CALLTYPE *coreclr_initialize_fn)(const char *exePath, const char *appDomainFriendlyName, int propertyCount, const char **propertyKeys, const char **propertyValues, void **hostHandle, unsigned int *domainId);
|
||||
|
||||
coreclr_create_delegate_fn coreclr_create_delegate = nullptr;
|
||||
coreclr_initialize_fn coreclr_initialize = nullptr;
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
static_assert(sizeof(char_t) == sizeof(char16_t));
|
||||
using HostFxrCharString = Char16String;
|
||||
|
|
@ -142,6 +150,56 @@ String find_hostfxr() {
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifndef TOOLS_ENABLED
|
||||
String find_monosgen() {
|
||||
#if defined(ANDROID_ENABLED)
|
||||
// Android includes all native libraries in the libs directory of the APK
|
||||
// so we assume it exists and use only the name to dlopen it.
|
||||
return "libmonosgen-2.0.so";
|
||||
#else
|
||||
#if defined(WINDOWS_ENABLED)
|
||||
String probe_path = GodotSharpDirs::get_api_assemblies_dir()
|
||||
.path_join("monosgen-2.0.dll");
|
||||
#elif defined(MACOS_ENABLED)
|
||||
String probe_path = GodotSharpDirs::get_api_assemblies_dir()
|
||||
.path_join("libmonosgen-2.0.dylib");
|
||||
#elif defined(UNIX_ENABLED)
|
||||
String probe_path = GodotSharpDirs::get_api_assemblies_dir()
|
||||
.path_join("libmonosgen-2.0.so");
|
||||
#else
|
||||
#error "Platform not supported (yet?)"
|
||||
#endif
|
||||
|
||||
if (FileAccess::exists(probe_path)) {
|
||||
return probe_path;
|
||||
}
|
||||
|
||||
return String();
|
||||
#endif
|
||||
}
|
||||
|
||||
String find_coreclr() {
|
||||
#if defined(WINDOWS_ENABLED)
|
||||
String probe_path = GodotSharpDirs::get_api_assemblies_dir()
|
||||
.path_join("coreclr.dll");
|
||||
#elif defined(MACOS_ENABLED)
|
||||
String probe_path = GodotSharpDirs::get_api_assemblies_dir()
|
||||
.path_join("libcoreclr.dylib");
|
||||
#elif defined(UNIX_ENABLED)
|
||||
String probe_path = GodotSharpDirs::get_api_assemblies_dir()
|
||||
.path_join("libcoreclr.so");
|
||||
#else
|
||||
#error "Platform not supported (yet?)"
|
||||
#endif
|
||||
|
||||
if (FileAccess::exists(probe_path)) {
|
||||
return probe_path;
|
||||
}
|
||||
|
||||
return String();
|
||||
}
|
||||
#endif
|
||||
|
||||
bool load_hostfxr(void *&r_hostfxr_dll_handle) {
|
||||
String hostfxr_path = find_hostfxr();
|
||||
|
||||
|
|
@ -182,6 +240,47 @@ bool load_hostfxr(void *&r_hostfxr_dll_handle) {
|
|||
hostfxr_close);
|
||||
}
|
||||
|
||||
#ifndef TOOLS_ENABLED
|
||||
bool load_coreclr(void *&r_coreclr_dll_handle) {
|
||||
String coreclr_path = find_coreclr();
|
||||
|
||||
bool is_monovm = false;
|
||||
if (coreclr_path.is_empty()) {
|
||||
// Fallback to MonoVM (should have the same API as CoreCLR).
|
||||
coreclr_path = find_monosgen();
|
||||
is_monovm = true;
|
||||
}
|
||||
|
||||
if (coreclr_path.is_empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const String coreclr_name = is_monovm ? "monosgen" : "coreclr";
|
||||
print_verbose("Found " + coreclr_name + ": " + coreclr_path);
|
||||
|
||||
Error err = OS::get_singleton()->open_dynamic_library(coreclr_path, r_coreclr_dll_handle);
|
||||
|
||||
if (err != OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void *lib = r_coreclr_dll_handle;
|
||||
|
||||
void *symbol = nullptr;
|
||||
|
||||
err = OS::get_singleton()->get_dynamic_library_symbol_handle(lib, "coreclr_initialize", symbol);
|
||||
ERR_FAIL_COND_V(err != OK, false);
|
||||
coreclr_initialize = (coreclr_initialize_fn)symbol;
|
||||
|
||||
err = OS::get_singleton()->get_dynamic_library_symbol_handle(lib, "coreclr_create_delegate", symbol);
|
||||
ERR_FAIL_COND_V(err != OK, false);
|
||||
coreclr_create_delegate = (coreclr_create_delegate_fn)symbol;
|
||||
|
||||
return (coreclr_initialize &&
|
||||
coreclr_create_delegate);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
load_assembly_and_get_function_pointer_fn initialize_hostfxr_for_config(const char_t *p_config_path) {
|
||||
hostfxr_handle cxt = nullptr;
|
||||
|
|
@ -264,7 +363,7 @@ godot_plugins_initialize_fn initialize_hostfxr_and_godot_plugins(bool &r_runtime
|
|||
|
||||
if (load_assembly_and_get_function_pointer == nullptr) {
|
||||
// Show a message box to the user to make the problem explicit (and explain a potential crash).
|
||||
OS::get_singleton()->alert(TTR("Unable to load .NET runtime, no compatible version was found.\nAttempting to create/edit a project will lead to a crash.\n\nPlease install the .NET SDK 6.0 or later from https://dotnet.microsoft.com/en-us/download and restart Godot."), TTR("Failed to load .NET runtime"));
|
||||
OS::get_singleton()->alert(TTR("Unable to load .NET runtime, no compatible version was found.\nAttempting to create/edit a project will lead to a crash.\n\nPlease install the .NET SDK 8.0 or later from https://get.dot.net and restart Godot."), TTR("Failed to load .NET runtime"));
|
||||
ERR_FAIL_V_MSG(nullptr, ".NET: Failed to load compatible .NET runtime");
|
||||
}
|
||||
|
||||
|
|
@ -289,7 +388,7 @@ godot_plugins_initialize_fn initialize_hostfxr_and_godot_plugins(bool &r_runtime
|
|||
String assembly_name = path::get_csharp_project_name();
|
||||
|
||||
HostFxrCharString assembly_path = str_to_hostfxr(GodotSharpDirs::get_api_assemblies_dir()
|
||||
.path_join(assembly_name + ".dll"));
|
||||
.path_join(assembly_name + ".dll"));
|
||||
|
||||
load_assembly_and_get_function_pointer_fn load_assembly_and_get_function_pointer =
|
||||
initialize_hostfxr_self_contained(get_data(assembly_path));
|
||||
|
|
@ -339,6 +438,56 @@ godot_plugins_initialize_fn try_load_native_aot_library(void *&r_aot_dll_handle)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef TOOLS_ENABLED
|
||||
String make_tpa_list() {
|
||||
String tpa_list;
|
||||
|
||||
#if defined(WINDOWS_ENABLED)
|
||||
String separator = ";";
|
||||
#else
|
||||
String separator = ":";
|
||||
#endif
|
||||
|
||||
String assemblies_dir = GodotSharpDirs::get_api_assemblies_dir();
|
||||
PackedStringArray files = DirAccess::get_files_at(assemblies_dir);
|
||||
for (const String &file : files) {
|
||||
tpa_list += assemblies_dir.path_join(file);
|
||||
tpa_list += separator;
|
||||
}
|
||||
|
||||
return tpa_list;
|
||||
}
|
||||
|
||||
godot_plugins_initialize_fn initialize_coreclr_and_godot_plugins(bool &r_runtime_initialized) {
|
||||
godot_plugins_initialize_fn godot_plugins_initialize = nullptr;
|
||||
|
||||
String assembly_name = path::get_csharp_project_name();
|
||||
|
||||
String tpa_list = make_tpa_list();
|
||||
const char *prop_keys[] = { "TRUSTED_PLATFORM_ASSEMBLIES" };
|
||||
const char *prop_values[] = { tpa_list.utf8().get_data() };
|
||||
int nprops = sizeof(prop_keys) / sizeof(prop_keys[0]);
|
||||
|
||||
void *coreclr_handle = nullptr;
|
||||
unsigned int domain_id = 0;
|
||||
int rc = coreclr_initialize(nullptr, nullptr, nprops, (const char **)&prop_keys, (const char **)&prop_values, &coreclr_handle, &domain_id);
|
||||
ERR_FAIL_COND_V_MSG(rc != 0, nullptr, ".NET: Failed to initialize CoreCLR.");
|
||||
|
||||
r_runtime_initialized = true;
|
||||
|
||||
print_verbose(".NET: CoreCLR initialized");
|
||||
|
||||
coreclr_create_delegate(coreclr_handle, domain_id,
|
||||
assembly_name.utf8().get_data(),
|
||||
"GodotPlugins.Game.Main",
|
||||
"InitializeFromGameProject",
|
||||
(void **)&godot_plugins_initialize);
|
||||
ERR_FAIL_NULL_V_MSG(godot_plugins_initialize, nullptr, ".NET: Failed to get GodotPlugins initialization function pointer");
|
||||
|
||||
return godot_plugins_initialize;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
bool GDMono::should_initialize() {
|
||||
|
|
@ -382,29 +531,31 @@ void GDMono::initialize() {
|
|||
}
|
||||
#endif
|
||||
|
||||
if (!load_hostfxr(hostfxr_dll_handle)) {
|
||||
if (load_hostfxr(hostfxr_dll_handle)) {
|
||||
godot_plugins_initialize = initialize_hostfxr_and_godot_plugins(runtime_initialized);
|
||||
ERR_FAIL_NULL(godot_plugins_initialize);
|
||||
} else {
|
||||
#if !defined(TOOLS_ENABLED)
|
||||
godot_plugins_initialize = try_load_native_aot_library(hostfxr_dll_handle);
|
||||
|
||||
if (godot_plugins_initialize != nullptr) {
|
||||
is_native_aot = true;
|
||||
runtime_initialized = true;
|
||||
if (load_coreclr(coreclr_dll_handle)) {
|
||||
godot_plugins_initialize = initialize_coreclr_and_godot_plugins(runtime_initialized);
|
||||
} else {
|
||||
godot_plugins_initialize = try_load_native_aot_library(hostfxr_dll_handle);
|
||||
if (godot_plugins_initialize != nullptr) {
|
||||
runtime_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (godot_plugins_initialize == nullptr) {
|
||||
ERR_FAIL_MSG(".NET: Failed to load hostfxr");
|
||||
}
|
||||
#else
|
||||
|
||||
// Show a message box to the user to make the problem explicit (and explain a potential crash).
|
||||
OS::get_singleton()->alert(TTR("Unable to load .NET runtime, specifically hostfxr.\nAttempting to create/edit a project will lead to a crash.\n\nPlease install the .NET SDK 6.0 or later from https://dotnet.microsoft.com/en-us/download and restart Godot."), TTR("Failed to load .NET runtime"));
|
||||
OS::get_singleton()->alert(TTR("Unable to load .NET runtime, specifically hostfxr.\nAttempting to create/edit a project will lead to a crash.\n\nPlease install the .NET SDK 8.0 or later from https://get.dot.net and restart Godot."), TTR("Failed to load .NET runtime"));
|
||||
ERR_FAIL_MSG(".NET: Failed to load hostfxr");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!is_native_aot) {
|
||||
godot_plugins_initialize = initialize_hostfxr_and_godot_plugins(runtime_initialized);
|
||||
ERR_FAIL_NULL(godot_plugins_initialize);
|
||||
}
|
||||
|
||||
int32_t interop_funcs_size = 0;
|
||||
const void **interop_funcs = godotsharp::get_runtime_interop_funcs(interop_funcs_size);
|
||||
|
||||
|
|
@ -553,6 +704,9 @@ GDMono::~GDMono() {
|
|||
if (hostfxr_dll_handle) {
|
||||
OS::get_singleton()->close_dynamic_library(hostfxr_dll_handle);
|
||||
}
|
||||
if (coreclr_dll_handle) {
|
||||
OS::get_singleton()->close_dynamic_library(coreclr_dll_handle);
|
||||
}
|
||||
|
||||
finalizing_scripts_domain = false;
|
||||
runtime_initialized = false;
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ class GDMono {
|
|||
bool finalizing_scripts_domain = false;
|
||||
|
||||
void *hostfxr_dll_handle = nullptr;
|
||||
bool is_native_aot = false;
|
||||
void *coreclr_dll_handle = nullptr;
|
||||
|
||||
String project_assembly_path;
|
||||
uint64_t project_assembly_modified_time = 0;
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ struct ManagedCallbacks {
|
|||
using FuncScriptManagerBridge_CreateManagedForGodotObjectBinding = GCHandleIntPtr(GD_CLR_STDCALL *)(const StringName *, Object *);
|
||||
using FuncScriptManagerBridge_CreateManagedForGodotObjectScriptInstance = bool(GD_CLR_STDCALL *)(const CSharpScript *, Object *, const Variant **, int32_t);
|
||||
using FuncScriptManagerBridge_GetScriptNativeName = void(GD_CLR_STDCALL *)(const CSharpScript *, StringName *);
|
||||
using FuncScriptManagerBridge_GetGlobalClassName = void(GD_CLR_STDCALL *)(const String *, String *, String *, String *);
|
||||
using FuncScriptManagerBridge_GetGlobalClassName = void(GD_CLR_STDCALL *)(const String *, String *, String *, bool *, bool *, String *);
|
||||
using FuncScriptManagerBridge_SetGodotObjectPtr = void(GD_CLR_STDCALL *)(GCHandleIntPtr, Object *);
|
||||
using FuncScriptManagerBridge_RaiseEventSignal = void(GD_CLR_STDCALL *)(GCHandleIntPtr, const StringName *, const Variant **, int32_t, bool *);
|
||||
using FuncScriptManagerBridge_ScriptIsOrInherits = bool(GD_CLR_STDCALL *)(const CSharpScript *, const CSharpScript *);
|
||||
|
|
|
|||
BIN
engine/modules/mono/thirdparty/libSystem.Security.Cryptography.Native.Android.jar
vendored
Executable file
BIN
engine/modules/mono/thirdparty/libSystem.Security.Cryptography.Native.Android.jar
vendored
Executable file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue