Merge pull request #48409 from neikeq/oh-im-die-ty-4ever
C#: Move marshaling logic and generated glue to C#
This commit is contained in:
commit
f580b1efdc
|
@ -7,21 +7,6 @@ Import("env_modules")
|
|||
|
||||
env_mono = env_modules.Clone()
|
||||
|
||||
if env_mono["tools"]:
|
||||
# NOTE: It is safe to generate this file here, since this is still executed serially
|
||||
import build_scripts.gen_cs_glue_version as gen_cs_glue_version
|
||||
|
||||
gen_cs_glue_version.generate_header("glue/GodotSharp", "glue/cs_glue_version.gen.h")
|
||||
|
||||
# Glue sources
|
||||
if env_mono["mono_glue"]:
|
||||
env_mono.Append(CPPDEFINES=["MONO_GLUE_ENABLED"])
|
||||
|
||||
import os.path
|
||||
|
||||
if not os.path.isfile("glue/mono_glue.gen.cpp"):
|
||||
raise RuntimeError("Mono glue sources not found. Did you forget to run '--generate-mono-glue'?")
|
||||
|
||||
if env_mono["tools"] or env_mono["target"] != "release":
|
||||
env_mono.Append(CPPDEFINES=["GD_MONO_HOT_RELOAD"])
|
||||
|
||||
|
@ -29,22 +14,6 @@ if env_mono["tools"] or env_mono["target"] != "release":
|
|||
|
||||
mono_configure.configure(env, env_mono)
|
||||
|
||||
if env_mono["tools"] and env_mono["mono_glue"] and env_mono["build_cil"]:
|
||||
# Build Godot API solution
|
||||
import build_scripts.api_solution_build as api_solution_build
|
||||
|
||||
api_sln_cmd = api_solution_build.build(env_mono)
|
||||
|
||||
# Build GodotTools
|
||||
import build_scripts.godot_tools_build as godot_tools_build
|
||||
|
||||
godot_tools_build.build(env_mono, api_sln_cmd)
|
||||
|
||||
# Build Godot.NET.Sdk
|
||||
import build_scripts.godot_net_sdk_build as godot_net_sdk_build
|
||||
|
||||
godot_net_sdk_build.build(env_mono)
|
||||
|
||||
# Add sources
|
||||
|
||||
env_mono.add_source_files(env.modules_sources, "*.cpp")
|
||||
|
@ -60,3 +29,5 @@ if env["platform"] in ["osx", "iphone"]:
|
|||
|
||||
if env["tools"]:
|
||||
env_mono.add_source_files(env.modules_sources, "editor/*.cpp")
|
||||
|
||||
env_mono.Prepend(CPPPATH=["#modules/gdnative/include/"])
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
# Build the Godot API solution
|
||||
|
||||
import os
|
||||
|
||||
from SCons.Script import Dir
|
||||
|
||||
|
||||
def build_api_solution(source, target, env):
|
||||
# source and target elements are of type SCons.Node.FS.File, hence why we convert them to str
|
||||
|
||||
module_dir = env["module_dir"]
|
||||
|
||||
solution_path = os.path.join(module_dir, "glue/GodotSharp/GodotSharp.sln")
|
||||
|
||||
build_config = env["solution_build_config"]
|
||||
|
||||
extra_msbuild_args = ["/p:NoWarn=1591"] # Ignore missing documentation warnings
|
||||
|
||||
from .solution_builder import build_solution
|
||||
|
||||
build_solution(env, solution_path, build_config, extra_msbuild_args=extra_msbuild_args)
|
||||
|
||||
# Copy targets
|
||||
|
||||
core_src_dir = os.path.abspath(os.path.join(solution_path, os.pardir, "GodotSharp", "bin", build_config))
|
||||
editor_src_dir = os.path.abspath(os.path.join(solution_path, os.pardir, "GodotSharpEditor", "bin", build_config))
|
||||
|
||||
dst_dir = os.path.abspath(os.path.join(str(target[0]), os.pardir))
|
||||
|
||||
if not os.path.isdir(dst_dir):
|
||||
assert not os.path.isfile(dst_dir)
|
||||
os.makedirs(dst_dir)
|
||||
|
||||
def copy_target(target_path):
|
||||
from shutil import copy
|
||||
|
||||
filename = os.path.basename(target_path)
|
||||
|
||||
src_path = os.path.join(core_src_dir, filename)
|
||||
if not os.path.isfile(src_path):
|
||||
src_path = os.path.join(editor_src_dir, filename)
|
||||
|
||||
copy(src_path, target_path)
|
||||
|
||||
for scons_target in target:
|
||||
copy_target(str(scons_target))
|
||||
|
||||
|
||||
def build(env_mono):
|
||||
assert env_mono["tools"]
|
||||
|
||||
target_filenames = [
|
||||
"GodotSharp.dll",
|
||||
"GodotSharp.pdb",
|
||||
"GodotSharp.xml",
|
||||
"GodotSharpEditor.dll",
|
||||
"GodotSharpEditor.pdb",
|
||||
"GodotSharpEditor.xml",
|
||||
]
|
||||
|
||||
depend_cmd = []
|
||||
|
||||
for build_config in ["Debug", "Release"]:
|
||||
output_dir = Dir("#bin").abspath
|
||||
editor_api_dir = os.path.join(output_dir, "GodotSharp", "Api", build_config)
|
||||
|
||||
targets = [os.path.join(editor_api_dir, filename) for filename in target_filenames]
|
||||
|
||||
cmd = env_mono.CommandNoCache(
|
||||
targets, depend_cmd, build_api_solution, module_dir=os.getcwd(), solution_build_config=build_config
|
||||
)
|
||||
env_mono.AlwaysBuild(cmd)
|
||||
|
||||
# Make the Release build of the API solution depend on the Debug build.
|
||||
# We do this in order to prevent SCons from building them in parallel,
|
||||
# which can freak out MSBuild. In many cases, one of the builds would
|
||||
# hang indefinitely requiring a key to be pressed for it to continue.
|
||||
depend_cmd = cmd
|
||||
|
||||
return depend_cmd
|
301
modules/mono/build_scripts/build_assemblies.py
Executable file
301
modules/mono/build_scripts/build_assemblies.py
Executable file
|
@ -0,0 +1,301 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
import os
|
||||
import os.path
|
||||
import shlex
|
||||
import subprocess
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
def find_dotnet_cli():
|
||||
if os.name == "nt":
|
||||
for hint_dir in os.environ["PATH"].split(os.pathsep):
|
||||
hint_dir = hint_dir.strip('"')
|
||||
hint_path = os.path.join(hint_dir, "dotnet")
|
||||
if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
|
||||
return hint_path
|
||||
if os.path.isfile(hint_path + ".exe") and os.access(hint_path + ".exe", os.X_OK):
|
||||
return hint_path + ".exe"
|
||||
else:
|
||||
for hint_dir in os.environ["PATH"].split(os.pathsep):
|
||||
hint_dir = hint_dir.strip('"')
|
||||
hint_path = os.path.join(hint_dir, "dotnet")
|
||||
if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
|
||||
return hint_path
|
||||
|
||||
|
||||
def find_msbuild_standalone_windows():
|
||||
msbuild_tools_path = find_msbuild_tools_path_reg()
|
||||
|
||||
if msbuild_tools_path:
|
||||
return os.path.join(msbuild_tools_path, "MSBuild.exe")
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def find_msbuild_mono_windows(mono_prefix):
|
||||
assert mono_prefix is not None
|
||||
|
||||
mono_bin_dir = os.path.join(mono_prefix, "bin")
|
||||
msbuild_mono = os.path.join(mono_bin_dir, "msbuild.bat")
|
||||
|
||||
if os.path.isfile(msbuild_mono):
|
||||
return msbuild_mono
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def find_msbuild_mono_unix():
|
||||
import sys
|
||||
|
||||
hint_dirs = []
|
||||
if sys.platform == "darwin":
|
||||
hint_dirs[:0] = [
|
||||
"/Library/Frameworks/Mono.framework/Versions/Current/bin",
|
||||
"/usr/local/var/homebrew/linked/mono/bin",
|
||||
]
|
||||
|
||||
for hint_dir in hint_dirs:
|
||||
hint_path = os.path.join(hint_dir, "msbuild")
|
||||
if os.path.isfile(hint_path):
|
||||
return hint_path
|
||||
elif os.path.isfile(hint_path + ".exe"):
|
||||
return hint_path + ".exe"
|
||||
|
||||
for hint_dir in os.environ["PATH"].split(os.pathsep):
|
||||
hint_dir = hint_dir.strip('"')
|
||||
hint_path = os.path.join(hint_dir, "msbuild")
|
||||
if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
|
||||
return hint_path
|
||||
if os.path.isfile(hint_path + ".exe") and os.access(hint_path + ".exe", os.X_OK):
|
||||
return hint_path + ".exe"
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def find_msbuild_tools_path_reg():
|
||||
import subprocess
|
||||
|
||||
program_files = os.getenv("PROGRAMFILES(X86)")
|
||||
if not program_files:
|
||||
program_files = os.getenv("PROGRAMFILES")
|
||||
vswhere = os.path.join(program_files, "Microsoft Visual Studio", "Installer", "vswhere.exe")
|
||||
|
||||
vswhere_args = ["-latest", "-products", "*", "-requires", "Microsoft.Component.MSBuild"]
|
||||
|
||||
try:
|
||||
lines = subprocess.check_output([vswhere] + vswhere_args).splitlines()
|
||||
|
||||
for line in lines:
|
||||
parts = line.decode("utf-8").split(":", 1)
|
||||
|
||||
if len(parts) < 2 or parts[0] != "installationPath":
|
||||
continue
|
||||
|
||||
val = parts[1].strip()
|
||||
|
||||
if not val:
|
||||
raise ValueError("Value of `installationPath` entry is empty")
|
||||
|
||||
# Since VS2019, the directory is simply named "Current"
|
||||
msbuild_dir = os.path.join(val, "MSBuild", "Current", "Bin")
|
||||
if os.path.isdir(msbuild_dir):
|
||||
return msbuild_dir
|
||||
|
||||
# Directory name "15.0" is used in VS 2017
|
||||
return os.path.join(val, "MSBuild", "15.0", "Bin")
|
||||
|
||||
raise ValueError("Cannot find `installationPath` entry")
|
||||
except ValueError as e:
|
||||
print("Error reading output from vswhere: " + str(e))
|
||||
except OSError:
|
||||
pass # Fine, vswhere not found
|
||||
except (subprocess.CalledProcessError, OSError):
|
||||
pass
|
||||
|
||||
|
||||
@dataclass
|
||||
class ToolsLocation:
|
||||
dotnet_cli: str = ""
|
||||
msbuild_standalone: str = ""
|
||||
msbuild_mono: str = ""
|
||||
mono_bin_dir: str = ""
|
||||
|
||||
|
||||
def find_any_msbuild_tool(mono_prefix):
|
||||
# Preference order: dotnet CLI > Standalone MSBuild > Mono's MSBuild
|
||||
|
||||
# Find dotnet CLI
|
||||
dotnet_cli = find_dotnet_cli()
|
||||
if dotnet_cli:
|
||||
return ToolsLocation(dotnet_cli=dotnet_cli)
|
||||
|
||||
# Find standalone MSBuild
|
||||
if os.name == "nt":
|
||||
msbuild_standalone = find_msbuild_standalone_windows()
|
||||
if msbuild_standalone:
|
||||
return ToolsLocation(msbuild_standalone=msbuild_standalone)
|
||||
|
||||
if mono_prefix:
|
||||
# Find Mono's MSBuild
|
||||
if os.name == "nt":
|
||||
msbuild_mono = find_msbuild_mono_windows(mono_prefix)
|
||||
if msbuild_mono:
|
||||
return ToolsLocation(msbuild_mono=msbuild_mono)
|
||||
else:
|
||||
msbuild_mono = find_msbuild_mono_unix()
|
||||
if msbuild_mono:
|
||||
return ToolsLocation(msbuild_mono=msbuild_mono)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def run_msbuild(tools: ToolsLocation, sln: str, msbuild_args: [str] = None):
|
||||
if msbuild_args is None:
|
||||
msbuild_args = []
|
||||
|
||||
using_msbuild_mono = False
|
||||
|
||||
# Preference order: dotnet CLI > Standalone MSBuild > Mono's MSBuild
|
||||
if tools.dotnet_cli:
|
||||
args = [tools.dotnet_cli, "msbuild"]
|
||||
elif tools.msbuild_standalone:
|
||||
args = [tools.msbuild_standalone]
|
||||
elif tools.msbuild_mono:
|
||||
args = [tools.msbuild_mono]
|
||||
using_msbuild_mono = True
|
||||
else:
|
||||
raise RuntimeError("Path to MSBuild or dotnet CLI not provided.")
|
||||
|
||||
args += [sln]
|
||||
|
||||
if len(msbuild_args) > 0:
|
||||
args += msbuild_args
|
||||
|
||||
print("Running MSBuild: ", " ".join(shlex.quote(arg) for arg in args), flush=True)
|
||||
|
||||
msbuild_env = os.environ.copy()
|
||||
|
||||
# Needed when running from Developer Command Prompt for VS
|
||||
if "PLATFORM" in msbuild_env:
|
||||
del msbuild_env["PLATFORM"]
|
||||
|
||||
if using_msbuild_mono:
|
||||
# The (Csc/Vbc/Fsc)ToolExe environment variables are required when
|
||||
# building with Mono's MSBuild. They must point to the batch files
|
||||
# in Mono's bin directory to make sure they are executed with Mono.
|
||||
msbuild_env.update(
|
||||
{
|
||||
"CscToolExe": os.path.join(tools.mono_bin_dir, "csc.bat"),
|
||||
"VbcToolExe": os.path.join(tools.mono_bin_dir, "vbc.bat"),
|
||||
"FscToolExe": os.path.join(tools.mono_bin_dir, "fsharpc.bat"),
|
||||
}
|
||||
)
|
||||
|
||||
return subprocess.call(args, env=msbuild_env)
|
||||
|
||||
|
||||
def build_godot_api(msbuild_tool, module_dir, output_dir):
|
||||
target_filenames = [
|
||||
"GodotSharp.dll",
|
||||
"GodotSharp.pdb",
|
||||
"GodotSharp.xml",
|
||||
"GodotSharpEditor.dll",
|
||||
"GodotSharpEditor.pdb",
|
||||
"GodotSharpEditor.xml",
|
||||
]
|
||||
|
||||
for build_config in ["Debug", "Release"]:
|
||||
editor_api_dir = os.path.join(output_dir, "GodotSharp", "Api", build_config)
|
||||
|
||||
targets = [os.path.join(editor_api_dir, filename) for filename in target_filenames]
|
||||
|
||||
sln = os.path.join(module_dir, "glue/GodotSharp/GodotSharp.sln")
|
||||
exit_code = run_msbuild(
|
||||
msbuild_tool,
|
||||
sln=sln,
|
||||
msbuild_args=["/restore", "/t:Build", "/p:Configuration=" + build_config, "/p:NoWarn=1591"],
|
||||
)
|
||||
if exit_code != 0:
|
||||
return exit_code
|
||||
|
||||
# Copy targets
|
||||
|
||||
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))
|
||||
|
||||
if not os.path.isdir(editor_api_dir):
|
||||
assert not os.path.isfile(editor_api_dir)
|
||||
os.makedirs(editor_api_dir)
|
||||
|
||||
def copy_target(target_path):
|
||||
from shutil import copy
|
||||
|
||||
filename = os.path.basename(target_path)
|
||||
|
||||
src_path = os.path.join(core_src_dir, filename)
|
||||
if not os.path.isfile(src_path):
|
||||
src_path = os.path.join(editor_src_dir, filename)
|
||||
|
||||
print(f"Copying assembly to {target_path}...")
|
||||
copy(src_path, target_path)
|
||||
|
||||
for scons_target in targets:
|
||||
copy_target(scons_target)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def build_all(msbuild_tool, module_dir, output_dir, godot_target, godot_platform):
|
||||
# Godot API
|
||||
exit_code = build_godot_api(msbuild_tool, module_dir, output_dir)
|
||||
if exit_code != 0:
|
||||
return exit_code
|
||||
|
||||
# GodotTools
|
||||
sln = os.path.join(module_dir, "editor/GodotTools/GodotTools.sln")
|
||||
args = ["/restore", "/t:Build", "/p:Configuration=" + ("Debug" if godot_target == "debug" else "Release")] + (
|
||||
["/p:GodotPlatform=" + godot_platform] if godot_platform else []
|
||||
)
|
||||
exit_code = run_msbuild(msbuild_tool, sln=sln, msbuild_args=args)
|
||||
if exit_code != 0:
|
||||
return exit_code
|
||||
|
||||
# Godot.NET.Sdk
|
||||
sln = os.path.join(module_dir, "editor/Godot.NET.Sdk/Godot.NET.Sdk.sln")
|
||||
exit_code = run_msbuild(msbuild_tool, sln=sln, msbuild_args=["/restore", "/t:Build", "/p:Configuration=Release"])
|
||||
if exit_code != 0:
|
||||
return exit_code
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
def main():
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
parser = argparse.ArgumentParser(description="Builds all Godot .NET solutions")
|
||||
parser.add_argument("--godot-output-dir", type=str, required=True)
|
||||
parser.add_argument("--godot-target", choices=["debug", "release_debug", "release"], type=str, required=True)
|
||||
parser.add_argument("--godot-platform", type=str, default="")
|
||||
parser.add_argument("--mono-prefix", type=str, default="")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
this_script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
module_dir = os.path.abspath(os.path.join(this_script_dir, os.pardir))
|
||||
|
||||
output_dir = os.path.abspath(args.godot_output_dir)
|
||||
|
||||
msbuild_tool = find_any_msbuild_tool(args.mono_prefix)
|
||||
|
||||
if msbuild_tool is None:
|
||||
print("Unable to find MSBuild")
|
||||
sys.exit(1)
|
||||
|
||||
exit_code = build_all(msbuild_tool, module_dir, output_dir, args.godot_target, args.godot_platform)
|
||||
sys.exit(exit_code)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,20 +0,0 @@
|
|||
def generate_header(solution_dir, version_header_dst):
|
||||
import os
|
||||
|
||||
latest_mtime = 0
|
||||
for root, dirs, files in os.walk(solution_dir, topdown=True):
|
||||
dirs[:] = [d for d in dirs if d not in ["Generated"]] # Ignored generated files
|
||||
files = [f for f in files if f.endswith(".cs")]
|
||||
for file in files:
|
||||
filepath = os.path.join(root, file)
|
||||
mtime = os.path.getmtime(filepath)
|
||||
latest_mtime = mtime if mtime > latest_mtime else latest_mtime
|
||||
|
||||
glue_version = int(latest_mtime) # The latest modified time will do for now
|
||||
|
||||
with open(version_header_dst, "w") as version_header:
|
||||
version_header.write("/* THIS FILE IS GENERATED DO NOT EDIT */\n")
|
||||
version_header.write("#ifndef CS_GLUE_VERSION_H\n")
|
||||
version_header.write("#define CS_GLUE_VERSION_H\n\n")
|
||||
version_header.write("#define CS_GLUE_VERSION UINT32_C(" + str(glue_version) + ")\n")
|
||||
version_header.write("\n#endif // CS_GLUE_VERSION_H\n")
|
|
@ -1,55 +0,0 @@
|
|||
# Build Godot.NET.Sdk solution
|
||||
|
||||
import os
|
||||
|
||||
from SCons.Script import Dir
|
||||
|
||||
|
||||
def build_godot_net_sdk(source, target, env):
|
||||
# source and target elements are of type SCons.Node.FS.File, hence why we convert them to str
|
||||
|
||||
module_dir = env["module_dir"]
|
||||
|
||||
solution_path = os.path.join(module_dir, "editor/Godot.NET.Sdk/Godot.NET.Sdk.sln")
|
||||
build_config = "Release"
|
||||
|
||||
from .solution_builder import build_solution
|
||||
|
||||
extra_msbuild_args = ["/p:GodotPlatform=" + env["platform"]]
|
||||
|
||||
build_solution(env, solution_path, build_config, extra_msbuild_args)
|
||||
# No need to copy targets. The Godot.NET.Sdk csproj takes care of copying them.
|
||||
|
||||
|
||||
def get_nupkgs_versions(props_file):
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
tree = ET.parse(props_file)
|
||||
root = tree.getroot()
|
||||
|
||||
return {
|
||||
"Godot.NET.Sdk": root.find("./PropertyGroup/PackageVersion_Godot_NET_Sdk").text.strip(),
|
||||
"Godot.SourceGenerators": root.find("./PropertyGroup/PackageVersion_Godot_SourceGenerators").text.strip(),
|
||||
}
|
||||
|
||||
|
||||
def build(env_mono):
|
||||
assert env_mono["tools"]
|
||||
|
||||
output_dir = Dir("#bin").abspath
|
||||
editor_tools_dir = os.path.join(output_dir, "GodotSharp", "Tools")
|
||||
nupkgs_dir = os.path.join(editor_tools_dir, "nupkgs")
|
||||
|
||||
module_dir = os.getcwd()
|
||||
|
||||
nupkgs_versions = get_nupkgs_versions(os.path.join(module_dir, "SdkPackageVersions.props"))
|
||||
|
||||
target_filenames = [
|
||||
"Godot.NET.Sdk.%s.nupkg" % nupkgs_versions["Godot.NET.Sdk"],
|
||||
"Godot.SourceGenerators.%s.nupkg" % nupkgs_versions["Godot.SourceGenerators"],
|
||||
]
|
||||
|
||||
targets = [os.path.join(nupkgs_dir, filename) for filename in target_filenames]
|
||||
|
||||
cmd = env_mono.CommandNoCache(targets, [], build_godot_net_sdk, module_dir=module_dir)
|
||||
env_mono.AlwaysBuild(cmd)
|
|
@ -1,38 +0,0 @@
|
|||
# Build GodotTools solution
|
||||
|
||||
import os
|
||||
|
||||
from SCons.Script import Dir
|
||||
|
||||
|
||||
def build_godot_tools(source, target, env):
|
||||
# source and target elements are of type SCons.Node.FS.File, hence why we convert them to str
|
||||
|
||||
module_dir = env["module_dir"]
|
||||
|
||||
solution_path = os.path.join(module_dir, "editor/GodotTools/GodotTools.sln")
|
||||
build_config = "Debug" if env["target"] == "debug" else "Release"
|
||||
|
||||
from .solution_builder import build_solution
|
||||
|
||||
extra_msbuild_args = ["/p:GodotPlatform=" + env["platform"]]
|
||||
|
||||
build_solution(env, solution_path, build_config, extra_msbuild_args)
|
||||
# No need to copy targets. The GodotTools csproj takes care of copying them.
|
||||
|
||||
|
||||
def build(env_mono, api_sln_cmd):
|
||||
assert env_mono["tools"]
|
||||
|
||||
output_dir = Dir("#bin").abspath
|
||||
editor_tools_dir = os.path.join(output_dir, "GodotSharp", "Tools")
|
||||
|
||||
target_filenames = ["GodotTools.dll"]
|
||||
|
||||
if env_mono["target"] == "debug":
|
||||
target_filenames += ["GodotTools.pdb"]
|
||||
|
||||
targets = [os.path.join(editor_tools_dir, filename) for filename in target_filenames]
|
||||
|
||||
cmd = env_mono.CommandNoCache(targets, api_sln_cmd, build_godot_tools, module_dir=os.getcwd())
|
||||
env_mono.AlwaysBuild(cmd)
|
|
@ -1,145 +0,0 @@
|
|||
import os
|
||||
|
||||
|
||||
verbose = False
|
||||
|
||||
|
||||
def find_dotnet_cli():
|
||||
import os.path
|
||||
|
||||
if os.name == "nt":
|
||||
for hint_dir in os.environ["PATH"].split(os.pathsep):
|
||||
hint_dir = hint_dir.strip('"')
|
||||
hint_path = os.path.join(hint_dir, "dotnet")
|
||||
if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
|
||||
return hint_path
|
||||
if os.path.isfile(hint_path + ".exe") and os.access(hint_path + ".exe", os.X_OK):
|
||||
return hint_path + ".exe"
|
||||
else:
|
||||
for hint_dir in os.environ["PATH"].split(os.pathsep):
|
||||
hint_dir = hint_dir.strip('"')
|
||||
hint_path = os.path.join(hint_dir, "dotnet")
|
||||
if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
|
||||
return hint_path
|
||||
|
||||
|
||||
def find_msbuild_unix():
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
hint_dirs = []
|
||||
if sys.platform == "darwin":
|
||||
hint_dirs[:0] = [
|
||||
"/Library/Frameworks/Mono.framework/Versions/Current/bin",
|
||||
"/usr/local/var/homebrew/linked/mono/bin",
|
||||
]
|
||||
|
||||
for hint_dir in hint_dirs:
|
||||
hint_path = os.path.join(hint_dir, "msbuild")
|
||||
if os.path.isfile(hint_path):
|
||||
return hint_path
|
||||
elif os.path.isfile(hint_path + ".exe"):
|
||||
return hint_path + ".exe"
|
||||
|
||||
for hint_dir in os.environ["PATH"].split(os.pathsep):
|
||||
hint_dir = hint_dir.strip('"')
|
||||
hint_path = os.path.join(hint_dir, "msbuild")
|
||||
if os.path.isfile(hint_path) and os.access(hint_path, os.X_OK):
|
||||
return hint_path
|
||||
if os.path.isfile(hint_path + ".exe") and os.access(hint_path + ".exe", os.X_OK):
|
||||
return hint_path + ".exe"
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def find_msbuild_windows(env):
|
||||
from .mono_reg_utils import find_mono_root_dir, find_msbuild_tools_path_reg
|
||||
|
||||
mono_root = env["mono_prefix"] or find_mono_root_dir(env["bits"])
|
||||
|
||||
if not mono_root:
|
||||
raise RuntimeError("Cannot find mono root directory")
|
||||
|
||||
mono_bin_dir = os.path.join(mono_root, "bin")
|
||||
msbuild_mono = os.path.join(mono_bin_dir, "msbuild.bat")
|
||||
|
||||
msbuild_tools_path = find_msbuild_tools_path_reg()
|
||||
|
||||
if msbuild_tools_path:
|
||||
return (os.path.join(msbuild_tools_path, "MSBuild.exe"), {})
|
||||
|
||||
if os.path.isfile(msbuild_mono):
|
||||
# The (Csc/Vbc/Fsc)ToolExe environment variables are required when
|
||||
# building with Mono's MSBuild. They must point to the batch files
|
||||
# in Mono's bin directory to make sure they are executed with Mono.
|
||||
mono_msbuild_env = {
|
||||
"CscToolExe": os.path.join(mono_bin_dir, "csc.bat"),
|
||||
"VbcToolExe": os.path.join(mono_bin_dir, "vbc.bat"),
|
||||
"FscToolExe": os.path.join(mono_bin_dir, "fsharpc.bat"),
|
||||
}
|
||||
return (msbuild_mono, mono_msbuild_env)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def run_command(command, args, env_override=None, name=None):
|
||||
def cmd_args_to_str(cmd_args):
|
||||
return " ".join([arg if not " " in arg else '"%s"' % arg for arg in cmd_args])
|
||||
|
||||
args = [command] + args
|
||||
|
||||
if name is None:
|
||||
name = os.path.basename(command)
|
||||
|
||||
if verbose:
|
||||
print("Running '%s': %s" % (name, cmd_args_to_str(args)))
|
||||
|
||||
import subprocess
|
||||
|
||||
try:
|
||||
if env_override is None:
|
||||
subprocess.check_call(args)
|
||||
else:
|
||||
subprocess.check_call(args, env=env_override)
|
||||
except subprocess.CalledProcessError as e:
|
||||
raise RuntimeError("'%s' exited with error code: %s" % (name, e.returncode))
|
||||
|
||||
|
||||
def build_solution(env, solution_path, build_config, extra_msbuild_args=[]):
|
||||
global verbose
|
||||
verbose = env["verbose"]
|
||||
|
||||
msbuild_env = os.environ.copy()
|
||||
|
||||
# Needed when running from Developer Command Prompt for VS
|
||||
if "PLATFORM" in msbuild_env:
|
||||
del msbuild_env["PLATFORM"]
|
||||
|
||||
msbuild_args = []
|
||||
|
||||
dotnet_cli = find_dotnet_cli()
|
||||
|
||||
if dotnet_cli:
|
||||
msbuild_path = dotnet_cli
|
||||
msbuild_args += ["msbuild"] # `dotnet msbuild` command
|
||||
else:
|
||||
# Find MSBuild
|
||||
if os.name == "nt":
|
||||
msbuild_info = find_msbuild_windows(env)
|
||||
if msbuild_info is None:
|
||||
raise RuntimeError("Cannot find MSBuild executable")
|
||||
msbuild_path = msbuild_info[0]
|
||||
msbuild_env.update(msbuild_info[1])
|
||||
else:
|
||||
msbuild_path = find_msbuild_unix()
|
||||
if msbuild_path is None:
|
||||
raise RuntimeError("Cannot find MSBuild executable")
|
||||
|
||||
print("MSBuild path: " + msbuild_path)
|
||||
|
||||
# Build solution
|
||||
|
||||
msbuild_args += [solution_path, "/restore", "/t:Build", "/p:Configuration=" + build_config]
|
||||
msbuild_args += extra_msbuild_args
|
||||
|
||||
run_command(msbuild_path, msbuild_args, env_override=msbuild_env, name="msbuild")
|
|
@ -2,7 +2,7 @@ supported_platforms = ["windows", "osx", "linuxbsd", "server", "android", "haiku
|
|||
|
||||
|
||||
def can_build(env, platform):
|
||||
return True
|
||||
return env["module_gdnative_enabled"]
|
||||
|
||||
|
||||
def configure(env):
|
||||
|
@ -36,7 +36,6 @@ def configure(env):
|
|||
)
|
||||
)
|
||||
envvars.Add(BoolVariable("mono_static", "Statically link Mono", default_mono_static))
|
||||
envvars.Add(BoolVariable("mono_glue", "Build with the Mono glue sources", True))
|
||||
envvars.Add(BoolVariable("build_cil", "Build C# solutions", True))
|
||||
envvars.Add(
|
||||
BoolVariable("copy_mono_root", "Make a copy of the Mono installation directory to bundle with the editor", True)
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
|
||||
#include "editor/editor_internal_calls.h"
|
||||
#include "godotsharp_dirs.h"
|
||||
#include "managed_callable.h"
|
||||
#include "mono_gd/gd_mono_cache.h"
|
||||
#include "mono_gd/gd_mono_class.h"
|
||||
#include "mono_gd/gd_mono_marshal.h"
|
||||
|
@ -105,6 +106,9 @@ Error CSharpLanguage::execute_file(const String &p_path) {
|
|||
return OK;
|
||||
}
|
||||
|
||||
extern void *godotsharp_pinvoke_funcs[95];
|
||||
[[maybe_unused]] volatile void **do_not_strip_godotsharp_pinvoke_funcs;
|
||||
|
||||
void CSharpLanguage::init() {
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
if (OS::get_singleton()->get_cmdline_args().find("--class-db-json")) {
|
||||
|
@ -115,20 +119,18 @@ void CSharpLanguage::init() {
|
|||
}
|
||||
#endif
|
||||
|
||||
gdmono = memnew(GDMono);
|
||||
gdmono->initialize();
|
||||
// Hopefully this will be enough for all compilers. Otherwise we could use the printf on fake getenv trick.
|
||||
do_not_strip_godotsharp_pinvoke_funcs = (volatile void **)godotsharp_pinvoke_funcs;
|
||||
|
||||
#if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED)
|
||||
// Generate bindings here, before loading assemblies. 'initialize_load_assemblies' aborts
|
||||
// the applications if the api assemblies or the main tools assembly is missing, but this
|
||||
// is not a problem for BindingsGenerator as it only needs the tools project editor assembly.
|
||||
// Generate the bindings here, before loading assemblies. The Godot assemblies
|
||||
// may be missing if the glue wasn't generated yet in order to build them.
|
||||
List<String> cmdline_args = OS::get_singleton()->get_cmdline_args();
|
||||
BindingsGenerator::handle_cmdline_args(cmdline_args);
|
||||
#endif
|
||||
|
||||
#ifndef MONO_GLUE_ENABLED
|
||||
print_line("Run this binary with '--generate-mono-glue path/to/modules/mono/glue'");
|
||||
#endif
|
||||
gdmono = memnew(GDMono);
|
||||
gdmono->initialize();
|
||||
|
||||
if (gdmono->is_runtime_initialized()) {
|
||||
gdmono->initialize_load_assemblies();
|
||||
|
@ -844,13 +846,13 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
|
|||
for (SelfList<ManagedCallable> *elem = ManagedCallable::instances.first(); elem; elem = elem->next()) {
|
||||
ManagedCallable *managed_callable = elem->self();
|
||||
|
||||
MonoDelegate *delegate = (MonoDelegate *)managed_callable->delegate_handle.get_target();
|
||||
|
||||
Array serialized_data;
|
||||
MonoObject *managed_serialized_data = GDMonoMarshal::variant_to_mono_object(serialized_data);
|
||||
|
||||
MonoException *exc = nullptr;
|
||||
bool success = (bool)CACHED_METHOD_THUNK(DelegateUtils, TrySerializeDelegate).invoke(delegate, managed_serialized_data, &exc);
|
||||
bool success = (bool)CACHED_METHOD_THUNK(DelegateUtils, TrySerializeDelegateWithGCHandle)
|
||||
.invoke(managed_callable->delegate_handle,
|
||||
managed_serialized_data, &exc);
|
||||
|
||||
if (exc) {
|
||||
GDMonoUtils::debug_print_unhandled_exception(exc);
|
||||
|
@ -1169,10 +1171,11 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
|
|||
const Array &serialized_data = elem.value;
|
||||
|
||||
MonoObject *managed_serialized_data = GDMonoMarshal::variant_to_mono_object(serialized_data);
|
||||
MonoDelegate *delegate = nullptr;
|
||||
void *delegate = nullptr;
|
||||
|
||||
MonoException *exc = nullptr;
|
||||
bool success = (bool)CACHED_METHOD_THUNK(DelegateUtils, TryDeserializeDelegate).invoke(managed_serialized_data, &delegate, &exc);
|
||||
bool success = (bool)CACHED_METHOD_THUNK(DelegateUtils, TryDeserializeDelegateWithGCHandle)
|
||||
.invoke(managed_serialized_data, &delegate, &exc);
|
||||
|
||||
if (exc) {
|
||||
GDMonoUtils::debug_print_unhandled_exception(exc);
|
||||
|
@ -1181,7 +1184,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
|
|||
|
||||
if (success) {
|
||||
ERR_CONTINUE(delegate == nullptr);
|
||||
managed_callable->set_delegate(delegate);
|
||||
managed_callable->delegate_handle = delegate;
|
||||
} else if (OS::get_singleton()->is_stdout_verbose()) {
|
||||
OS::get_singleton()->print("Failed to deserialize delegate\n");
|
||||
}
|
||||
|
@ -1309,7 +1312,7 @@ bool CSharpLanguage::debug_break(const String &p_error, bool p_allow_continue) {
|
|||
}
|
||||
}
|
||||
|
||||
void CSharpLanguage::_on_scripts_domain_unloaded() {
|
||||
void CSharpLanguage::_on_scripts_domain_about_to_unload() {
|
||||
for (KeyValue<Object *, CSharpScriptBinding> &E : script_bindings) {
|
||||
CSharpScriptBinding &script_binding = E.value;
|
||||
script_binding.gchandle.release();
|
||||
|
@ -1322,8 +1325,7 @@ void CSharpLanguage::_on_scripts_domain_unloaded() {
|
|||
|
||||
for (SelfList<ManagedCallable> *elem = ManagedCallable::instances.first(); elem; elem = elem->next()) {
|
||||
ManagedCallable *managed_callable = elem->self();
|
||||
managed_callable->delegate_handle.release();
|
||||
managed_callable->delegate_invoke = nullptr;
|
||||
managed_callable->release_delegate_handle();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1657,7 +1659,7 @@ bool CSharpInstance::set(const StringName &p_name, const Variant &p_value) {
|
|||
GDMonoProperty *property = top->get_property(p_name);
|
||||
|
||||
if (property) {
|
||||
property->set_value(mono_object, GDMonoMarshal::variant_to_mono_object(p_value, property->get_type()));
|
||||
property->set_value(mono_object, GDMonoMarshal::variant_to_mono_object_of_type(p_value, property->get_type()));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1794,7 +1796,8 @@ void CSharpInstance::get_event_signals_state_for_reloading(List<Pair<StringName,
|
|||
MonoObject *managed_serialized_data = GDMonoMarshal::variant_to_mono_object(serialized_data);
|
||||
|
||||
MonoException *exc = nullptr;
|
||||
bool success = (bool)CACHED_METHOD_THUNK(DelegateUtils, TrySerializeDelegate).invoke(delegate_field_value, managed_serialized_data, &exc);
|
||||
bool success = (bool)CACHED_METHOD_THUNK(DelegateUtils, TrySerializeDelegate)
|
||||
.invoke(delegate_field_value, managed_serialized_data, &exc);
|
||||
|
||||
if (exc) {
|
||||
GDMonoUtils::debug_print_unhandled_exception(exc);
|
||||
|
|
|
@ -393,7 +393,7 @@ class CSharpLanguage : public ScriptLanguage {
|
|||
String _debug_error;
|
||||
|
||||
friend class GDMono;
|
||||
void _on_scripts_domain_unloaded();
|
||||
void _on_scripts_domain_about_to_unload();
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
EditorPlugin *godotsharp_editor = nullptr;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -218,6 +218,11 @@ class BindingsGenerator {
|
|||
bool is_singleton = false;
|
||||
bool is_ref_counted = false;
|
||||
|
||||
/**
|
||||
* Determines whether the
|
||||
*/
|
||||
bool c_type_is_disposable_struct = false;
|
||||
|
||||
/**
|
||||
* Used only by Object-derived types.
|
||||
* Determines if this type is not abstract (incomplete).
|
||||
|
@ -232,32 +237,35 @@ class BindingsGenerator {
|
|||
*/
|
||||
bool memory_own = false;
|
||||
|
||||
/**
|
||||
* This must be set to true for any struct bigger than 32-bits. Those cannot be passed/returned by value
|
||||
* with internal calls, so we must use pointers instead. Returns must be replace with out parameters.
|
||||
* In this case, [c_out] and [cs_out] must have a different format, explained below.
|
||||
* The Mono IL interpreter icall trampolines don't support passing structs bigger than 32-bits by value (at least not on WASM).
|
||||
*/
|
||||
bool ret_as_byref_arg = false;
|
||||
|
||||
// !! The comments of the following fields make reference to other fields via square brackets, e.g.: [field_name]
|
||||
// !! When renaming those fields, make sure to rename their references in the comments
|
||||
|
||||
// --- C INTERFACE ---
|
||||
|
||||
static const char *DEFAULT_VARARG_C_IN;
|
||||
|
||||
/**
|
||||
* One or more statements that manipulate the parameter before being passed as argument of a ptrcall.
|
||||
* If the statement adds a local that must be passed as the argument instead of the parameter,
|
||||
* the name of that local must be specified with [c_arg_in].
|
||||
* For variadic methods, this field is required and, if empty, [DEFAULT_VARARG_C_IN] is used instead.
|
||||
* Formatting elements:
|
||||
* %0: [c_type] of the parameter
|
||||
* %1: name of the parameter
|
||||
* %2-4: reserved
|
||||
* %5: indentation text
|
||||
*/
|
||||
String c_in;
|
||||
|
||||
/**
|
||||
* One or more statements that manipulate the parameter before being passed as argument of a vararg call.
|
||||
* If the statement adds a local that must be passed as the argument instead of the parameter,
|
||||
* the name of that local must be specified with [c_arg_in].
|
||||
* Formatting elements:
|
||||
* %0: [c_type] of the parameter
|
||||
* %1: name of the parameter
|
||||
* %2-4: reserved
|
||||
* %5: indentation text
|
||||
*/
|
||||
String c_in_vararg;
|
||||
|
||||
/**
|
||||
* Determines the expression that will be passed as argument to ptrcall.
|
||||
* By default the value equals the name of the parameter,
|
||||
|
@ -281,7 +289,8 @@ class BindingsGenerator {
|
|||
* %0: [c_type_out] of the return type
|
||||
* %1: name of the variable to be returned
|
||||
* %2: [name] of the return type
|
||||
* %3: name of the parameter that must be assigned the return value
|
||||
* %3-4: reserved
|
||||
* %5: indentation text
|
||||
*/
|
||||
String c_out;
|
||||
|
||||
|
@ -320,6 +329,7 @@ class BindingsGenerator {
|
|||
* %0 or %s: name of the parameter
|
||||
*/
|
||||
String cs_in;
|
||||
bool cs_in_is_unsafe = false;
|
||||
|
||||
/**
|
||||
* One or more statements that determine how a variable of this type is returned from a method.
|
||||
|
@ -328,7 +338,9 @@ class BindingsGenerator {
|
|||
* %0: internal method name
|
||||
* %1: internal method call arguments without surrounding parenthesis
|
||||
* %2: [cs_type] of the return type
|
||||
* %3: [im_type_out] of the return type
|
||||
* %3: [c_type_out] of the return type
|
||||
* %4: reserved
|
||||
* %5: indentation text
|
||||
*/
|
||||
String cs_out;
|
||||
|
||||
|
@ -338,16 +350,6 @@ class BindingsGenerator {
|
|||
*/
|
||||
String cs_type;
|
||||
|
||||
/**
|
||||
* Type used for parameters of internal call methods.
|
||||
*/
|
||||
String im_type_in;
|
||||
|
||||
/**
|
||||
* Type used for the return type of internal call methods.
|
||||
*/
|
||||
String im_type_out;
|
||||
|
||||
const DocData::ClassDoc *class_doc = nullptr;
|
||||
|
||||
List<ConstantInterface> constants;
|
||||
|
@ -402,8 +404,8 @@ class BindingsGenerator {
|
|||
|
||||
itype.c_type = itype.name;
|
||||
itype.cs_type = itype.proxy_name;
|
||||
itype.im_type_in = "ref " + itype.proxy_name;
|
||||
itype.im_type_out = itype.proxy_name;
|
||||
itype.c_type_in = itype.proxy_name + "*";
|
||||
itype.c_type_out = itype.proxy_name;
|
||||
itype.class_doc = &EditorHelp::get_doc_data()->class_list[itype.proxy_name];
|
||||
}
|
||||
|
||||
|
@ -437,65 +439,26 @@ class BindingsGenerator {
|
|||
return itype;
|
||||
}
|
||||
|
||||
static void create_placeholder_type(TypeInterface &r_itype, const StringName &p_cname) {
|
||||
r_itype.name = p_cname;
|
||||
r_itype.cname = p_cname;
|
||||
r_itype.proxy_name = r_itype.name;
|
||||
|
||||
r_itype.c_type = r_itype.name;
|
||||
r_itype.c_type_in = "MonoObject*";
|
||||
r_itype.c_type_out = "MonoObject*";
|
||||
r_itype.cs_type = r_itype.proxy_name;
|
||||
r_itype.im_type_in = r_itype.proxy_name;
|
||||
r_itype.im_type_out = r_itype.proxy_name;
|
||||
}
|
||||
|
||||
static void postsetup_enum_type(TypeInterface &r_enum_itype) {
|
||||
// C interface for enums is the same as that of 'uint32_t'. Remember to apply
|
||||
// any of the changes done here to the 'uint32_t' type interface as well.
|
||||
|
||||
r_enum_itype.c_arg_in = "&%s_in";
|
||||
{
|
||||
// The expected types for parameters and return value in ptrcall are 'int64_t' or 'uint64_t'.
|
||||
r_enum_itype.c_in = "\t%0 %1_in = (%0)%1;\n";
|
||||
r_enum_itype.c_out = "\treturn (%0)%1;\n";
|
||||
r_enum_itype.c_type = "int64_t";
|
||||
}
|
||||
r_enum_itype.c_type_in = "int32_t";
|
||||
r_enum_itype.c_type_out = r_enum_itype.c_type_in;
|
||||
|
||||
r_enum_itype.cs_type = r_enum_itype.proxy_name;
|
||||
r_enum_itype.cs_in = "(int)%s";
|
||||
r_enum_itype.cs_out = "return (%2)%0(%1);";
|
||||
r_enum_itype.im_type_in = "int";
|
||||
r_enum_itype.im_type_out = "int";
|
||||
r_enum_itype.class_doc = &EditorHelp::get_doc_data()->class_list[r_enum_itype.proxy_name];
|
||||
}
|
||||
static void postsetup_enum_type(TypeInterface &r_enum_itype);
|
||||
|
||||
TypeInterface() {}
|
||||
};
|
||||
|
||||
struct InternalCall {
|
||||
String name;
|
||||
String im_type_out; // Return type for the C# method declaration. Also used as companion of [unique_siq]
|
||||
String im_sig; // Signature for the C# method declaration
|
||||
String unique_sig; // Unique signature to avoid duplicates in containers
|
||||
bool editor_only = false;
|
||||
|
||||
bool is_vararg;
|
||||
TypeReference return_type;
|
||||
List<TypeReference> argument_types;
|
||||
|
||||
_FORCE_INLINE_ int get_arguments_count() const { return argument_types.size(); }
|
||||
|
||||
InternalCall() {}
|
||||
|
||||
InternalCall(const String &p_name, const String &p_im_type_out, const String &p_im_sig = String(), const String &p_unique_sig = String()) {
|
||||
InternalCall(ClassDB::APIType api_type, const String &p_name, const String &p_unique_sig = String()) {
|
||||
name = p_name;
|
||||
im_type_out = p_im_type_out;
|
||||
im_sig = p_im_sig;
|
||||
unique_sig = p_unique_sig;
|
||||
editor_only = false;
|
||||
}
|
||||
|
||||
InternalCall(ClassDB::APIType api_type, const String &p_name, const String &p_im_type_out, const String &p_im_sig = String(), const String &p_unique_sig = String()) {
|
||||
name = p_name;
|
||||
im_type_out = p_im_type_out;
|
||||
im_sig = p_im_sig;
|
||||
unique_sig = p_unique_sig;
|
||||
editor_only = api_type == ClassDB::API_EDITOR;
|
||||
}
|
||||
|
@ -510,7 +473,6 @@ class BindingsGenerator {
|
|||
|
||||
OrderedHashMap<StringName, TypeInterface> obj_types;
|
||||
|
||||
Map<StringName, TypeInterface> placeholder_types;
|
||||
Map<StringName, TypeInterface> builtin_types;
|
||||
Map<StringName, TypeInterface> enum_types;
|
||||
|
||||
|
@ -518,13 +480,9 @@ class BindingsGenerator {
|
|||
List<ConstantInterface> global_constants;
|
||||
|
||||
List<InternalCall> method_icalls;
|
||||
/// Stores the unique internal calls from [method_icalls] that are assigned to each method.
|
||||
Map<const MethodInterface *, const InternalCall *> method_icalls_map;
|
||||
|
||||
List<const InternalCall *> generated_icall_funcs;
|
||||
|
||||
List<InternalCall> core_custom_icalls;
|
||||
List<InternalCall> editor_custom_icalls;
|
||||
|
||||
Map<StringName, List<StringName>> blacklisted_methods;
|
||||
|
||||
void _initialize_blacklisted_methods();
|
||||
|
@ -536,6 +494,8 @@ class BindingsGenerator {
|
|||
StringName type_Object = StaticCString::create("Object");
|
||||
StringName type_RefCounted = StaticCString::create("RefCounted");
|
||||
StringName type_RID = StaticCString::create("RID");
|
||||
StringName type_Callable = StaticCString::create("Callable");
|
||||
StringName type_Signal = StaticCString::create("Signal");
|
||||
StringName type_String = StaticCString::create("String");
|
||||
StringName type_StringName = StaticCString::create("StringName");
|
||||
StringName type_NodePath = StaticCString::create("NodePath");
|
||||
|
@ -601,17 +561,6 @@ class BindingsGenerator {
|
|||
|
||||
NameCache name_cache;
|
||||
|
||||
const List<InternalCall>::Element *find_icall_by_name(const String &p_name, const List<InternalCall> &p_list) {
|
||||
const List<InternalCall>::Element *it = p_list.front();
|
||||
while (it) {
|
||||
if (it->get().name == p_name) {
|
||||
return it;
|
||||
}
|
||||
it = it->next();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ConstantInterface *find_constant_by_name(const String &p_name, const List<ConstantInterface> &p_constants) const {
|
||||
for (const ConstantInterface &E : p_constants) {
|
||||
if (E.name == p_name) {
|
||||
|
@ -622,10 +571,9 @@ class BindingsGenerator {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
inline String get_unique_sig(const TypeInterface &p_type) {
|
||||
if (p_type.is_ref_counted) {
|
||||
return "Ref";
|
||||
} else if (p_type.is_object_type) {
|
||||
inline String get_arg_unique_sig(const TypeInterface &p_type) {
|
||||
// For parameters, we treat reference and non-reference derived types the same.
|
||||
if (p_type.is_object_type) {
|
||||
return "Obj";
|
||||
} else if (p_type.is_enum) {
|
||||
return "int";
|
||||
|
@ -634,15 +582,27 @@ class BindingsGenerator {
|
|||
return p_type.name;
|
||||
}
|
||||
|
||||
inline String get_ret_unique_sig(const TypeInterface *p_type) {
|
||||
// Reference derived return types are treated differently.
|
||||
if (p_type->is_ref_counted) {
|
||||
return "Ref";
|
||||
} else if (p_type->is_object_type) {
|
||||
return "Obj";
|
||||
} else if (p_type->is_enum) {
|
||||
return "int";
|
||||
}
|
||||
|
||||
return p_type->name;
|
||||
}
|
||||
|
||||
String bbcode_to_xml(const String &p_bbcode, const TypeInterface *p_itype);
|
||||
|
||||
int _determine_enum_prefix(const EnumInterface &p_ienum);
|
||||
void _apply_prefix_to_enum_constants(EnumInterface &p_ienum, int p_prefix_length);
|
||||
|
||||
void _generate_method_icalls(const TypeInterface &p_itype);
|
||||
Error _populate_method_icalls_table(const TypeInterface &p_itype);
|
||||
|
||||
const TypeInterface *_get_type_or_null(const TypeReference &p_typeref);
|
||||
const TypeInterface *_get_type_or_placeholder(const TypeReference &p_typeref);
|
||||
|
||||
StringName _get_int_type_name_from_meta(GodotTypeInfo::Metadata p_meta);
|
||||
StringName _get_float_type_name_from_meta(GodotTypeInfo::Metadata p_meta);
|
||||
|
@ -661,11 +621,11 @@ class BindingsGenerator {
|
|||
Error _generate_cs_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output);
|
||||
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);
|
||||
|
||||
void _generate_array_extensions(StringBuilder &p_output);
|
||||
void _generate_global_constants(StringBuilder &p_output);
|
||||
|
||||
Error _generate_glue_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, StringBuilder &p_output);
|
||||
|
||||
Error _save_file(const String &p_path, const StringBuilder &p_content);
|
||||
|
||||
void _log(const char *p_format, ...) _PRINTF_FORMAT_ATTRIBUTE_2_3;
|
||||
|
@ -676,15 +636,12 @@ public:
|
|||
Error generate_cs_core_project(const String &p_proj_dir);
|
||||
Error generate_cs_editor_project(const String &p_proj_dir);
|
||||
Error generate_cs_api(const String &p_output_dir);
|
||||
Error generate_glue(const String &p_output_dir);
|
||||
|
||||
_FORCE_INLINE_ bool is_log_print_enabled() { return log_print_enabled; }
|
||||
_FORCE_INLINE_ void set_log_print_enabled(bool p_enabled) { log_print_enabled = p_enabled; }
|
||||
|
||||
_FORCE_INLINE_ bool is_initialized() { return initialized; }
|
||||
|
||||
static uint32_t get_version();
|
||||
|
||||
static void handle_cmdline_args(const List<String> &p_cmdline_args);
|
||||
|
||||
BindingsGenerator() {
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
#include "main/main.h"
|
||||
|
||||
#include "../csharp_script.h"
|
||||
#include "../glue/cs_glue_version.gen.h"
|
||||
#include "../godotsharp_dirs.h"
|
||||
#include "../mono_gd/gd_mono_marshal.h"
|
||||
#include "../utils/osx_utils.h"
|
||||
|
|
7
modules/mono/glue/GodotSharp/GodotSharp.sln.DotSettings
Normal file
7
modules/mono/glue/GodotSharp/GodotSharp.sln.DotSettings
Normal file
|
@ -0,0 +1,7 @@
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GC/@EntryIndexedValue">GC</s:String>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=gdnative/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=godotsharp/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=icall/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=quat/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=vcall/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
|
@ -1,47 +1,28 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
namespace Godot.Collections
|
||||
{
|
||||
class ArraySafeHandle : SafeHandle
|
||||
{
|
||||
public ArraySafeHandle(IntPtr handle) : base(IntPtr.Zero, true)
|
||||
{
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
public override bool IsInvalid
|
||||
{
|
||||
get { return handle == IntPtr.Zero; }
|
||||
}
|
||||
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
Array.godot_icall_Array_Dtor(handle);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper around Godot's Array class, an array of Variant
|
||||
/// typed elements allocated in the engine in C++. Useful when
|
||||
/// interfacing with the engine. Otherwise prefer .NET collections
|
||||
/// such as <see cref="System.Array"/> or <see cref="List{T}"/>.
|
||||
/// </summary>
|
||||
public class Array : IList, IDisposable
|
||||
public sealed class Array : IList, IDisposable
|
||||
{
|
||||
ArraySafeHandle safeHandle;
|
||||
bool disposed = false;
|
||||
internal godot_array NativeValue;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new empty <see cref="Array"/>.
|
||||
/// </summary>
|
||||
public Array()
|
||||
{
|
||||
safeHandle = new ArraySafeHandle(godot_icall_Array_Ctor());
|
||||
godot_icall_Array_Ctor(out NativeValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -58,6 +39,7 @@ namespace Godot.Collections
|
|||
Add(element);
|
||||
}
|
||||
|
||||
// TODO: This must be removed. Lots of silent mistakes as it takes pretty much anything.
|
||||
/// <summary>
|
||||
/// Constructs a new <see cref="Array"/> from the given objects.
|
||||
/// </summary>
|
||||
|
@ -69,25 +51,37 @@ namespace Godot.Collections
|
|||
{
|
||||
throw new NullReferenceException($"Parameter '{nameof(array)} cannot be null.'");
|
||||
}
|
||||
safeHandle = new ArraySafeHandle(godot_icall_Array_Ctor_MonoArray(array));
|
||||
|
||||
godot_icall_Array_Ctor_MonoArray(array, out NativeValue);
|
||||
}
|
||||
|
||||
internal Array(ArraySafeHandle handle)
|
||||
private Array(godot_array nativeValueToOwn)
|
||||
{
|
||||
safeHandle = handle;
|
||||
NativeValue = nativeValueToOwn;
|
||||
}
|
||||
|
||||
internal Array(IntPtr handle)
|
||||
// Explicit name to make it very clear
|
||||
internal static Array CreateTakingOwnershipOfDisposableValue(godot_array nativeValueToOwn)
|
||||
=> new Array(nativeValueToOwn);
|
||||
|
||||
~Array()
|
||||
{
|
||||
safeHandle = new ArraySafeHandle(handle);
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
internal IntPtr GetPtr()
|
||||
/// <summary>
|
||||
/// Disposes of this <see cref="Array"/>.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (disposed)
|
||||
throw new ObjectDisposedException(GetType().FullName);
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
return safeHandle.DangerousGetHandle();
|
||||
public void Dispose(bool disposing)
|
||||
{
|
||||
// Always dispose `NativeValue` even if disposing is true
|
||||
NativeValue.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -97,7 +91,9 @@ namespace Godot.Collections
|
|||
/// <returns>A new Godot Array.</returns>
|
||||
public Array Duplicate(bool deep = false)
|
||||
{
|
||||
return new Array(godot_icall_Array_Duplicate(GetPtr(), deep));
|
||||
godot_array newArray;
|
||||
godot_icall_Array_Duplicate(ref NativeValue, deep, out newArray);
|
||||
return CreateTakingOwnershipOfDisposableValue(newArray);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -107,7 +103,7 @@ namespace Godot.Collections
|
|||
/// <returns><see cref="Error.Ok"/> if successful, or an error code.</returns>
|
||||
public Error Resize(int newSize)
|
||||
{
|
||||
return godot_icall_Array_Resize(GetPtr(), newSize);
|
||||
return godot_icall_Array_Resize(ref NativeValue, newSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -115,7 +111,7 @@ namespace Godot.Collections
|
|||
/// </summary>
|
||||
public void Shuffle()
|
||||
{
|
||||
godot_icall_Array_Shuffle(GetPtr());
|
||||
godot_icall_Array_Shuffle(ref NativeValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -126,26 +122,9 @@ namespace Godot.Collections
|
|||
/// <returns>A new Godot Array with the contents of both arrays.</returns>
|
||||
public static Array operator +(Array left, Array right)
|
||||
{
|
||||
return new Array(godot_icall_Array_Concatenate(left.GetPtr(), right.GetPtr()));
|
||||
}
|
||||
|
||||
// IDisposable
|
||||
|
||||
/// <summary>
|
||||
/// Disposes of this <see cref="Array"/>.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (disposed)
|
||||
return;
|
||||
|
||||
if (safeHandle != null)
|
||||
{
|
||||
safeHandle.Dispose();
|
||||
safeHandle = null;
|
||||
}
|
||||
|
||||
disposed = true;
|
||||
godot_array newArray;
|
||||
godot_icall_Array_Concatenate(ref left.NativeValue, ref right.NativeValue, out newArray);
|
||||
return CreateTakingOwnershipOfDisposableValue(newArray);
|
||||
}
|
||||
|
||||
// IList
|
||||
|
@ -160,8 +139,16 @@ namespace Godot.Collections
|
|||
/// <value>The object at the given index.</value>
|
||||
public object this[int index]
|
||||
{
|
||||
get => godot_icall_Array_At(GetPtr(), index);
|
||||
set => godot_icall_Array_SetAt(GetPtr(), index, value);
|
||||
get
|
||||
{
|
||||
godot_icall_Array_At(ref NativeValue, index, out godot_variant elem);
|
||||
unsafe
|
||||
{
|
||||
using (elem)
|
||||
return Marshaling.variant_to_mono_object(&elem);
|
||||
}
|
||||
}
|
||||
set => godot_icall_Array_SetAt(ref NativeValue, index, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -170,19 +157,19 @@ namespace Godot.Collections
|
|||
/// </summary>
|
||||
/// <param name="value">The object to add.</param>
|
||||
/// <returns>The new size after adding the object.</returns>
|
||||
public int Add(object value) => godot_icall_Array_Add(GetPtr(), value);
|
||||
public int Add(object value) => godot_icall_Array_Add(ref NativeValue, value);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this <see cref="Array"/> contains the given object.
|
||||
/// </summary>
|
||||
/// <param name="value">The item to look for.</param>
|
||||
/// <returns>Whether or not this array contains the given object.</returns>
|
||||
public bool Contains(object value) => godot_icall_Array_Contains(GetPtr(), value);
|
||||
public bool Contains(object value) => godot_icall_Array_Contains(ref NativeValue, value);
|
||||
|
||||
/// <summary>
|
||||
/// Erases all items from this <see cref="Array"/>.
|
||||
/// </summary>
|
||||
public void Clear() => godot_icall_Array_Clear(GetPtr());
|
||||
public void Clear() => godot_icall_Array_Clear(ref NativeValue);
|
||||
|
||||
/// <summary>
|
||||
/// Searches this <see cref="Array"/> for an object
|
||||
|
@ -190,7 +177,7 @@ namespace Godot.Collections
|
|||
/// </summary>
|
||||
/// <param name="value">The object to search for.</param>
|
||||
/// <returns>The index of the object, or -1 if not found.</returns>
|
||||
public int IndexOf(object value) => godot_icall_Array_IndexOf(GetPtr(), value);
|
||||
public int IndexOf(object value) => godot_icall_Array_IndexOf(ref NativeValue, value);
|
||||
|
||||
/// <summary>
|
||||
/// Inserts a new object at a given position in the array.
|
||||
|
@ -200,20 +187,20 @@ namespace Godot.Collections
|
|||
/// </summary>
|
||||
/// <param name="index">The index to insert at.</param>
|
||||
/// <param name="value">The object to insert.</param>
|
||||
public void Insert(int index, object value) => godot_icall_Array_Insert(GetPtr(), index, value);
|
||||
public void Insert(int index, object value) => godot_icall_Array_Insert(ref NativeValue, index, value);
|
||||
|
||||
/// <summary>
|
||||
/// Removes the first occurrence of the specified value
|
||||
/// from this <see cref="Array"/>.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to remove.</param>
|
||||
public void Remove(object value) => godot_icall_Array_Remove(GetPtr(), value);
|
||||
public void Remove(object value) => godot_icall_Array_Remove(ref NativeValue, value);
|
||||
|
||||
/// <summary>
|
||||
/// Removes an element from this <see cref="Array"/> by index.
|
||||
/// </summary>
|
||||
/// <param name="index">The index of the element to remove.</param>
|
||||
public void RemoveAt(int index) => godot_icall_Array_RemoveAt(GetPtr(), index);
|
||||
public void RemoveAt(int index) => godot_icall_Array_RemoveAt(ref NativeValue, index);
|
||||
|
||||
// ICollection
|
||||
|
||||
|
@ -222,7 +209,7 @@ namespace Godot.Collections
|
|||
/// This is also known as the size or length of the array.
|
||||
/// </summary>
|
||||
/// <returns>The number of elements.</returns>
|
||||
public int Count => godot_icall_Array_Count(GetPtr());
|
||||
public int Count => godot_icall_Array_Count(ref NativeValue);
|
||||
|
||||
object ICollection.SyncRoot => this;
|
||||
|
||||
|
@ -243,7 +230,7 @@ namespace Godot.Collections
|
|||
throw new ArgumentOutOfRangeException(nameof(index), "Number was less than the array's lower bound in the first dimension.");
|
||||
|
||||
// Internal call may throw ArgumentException
|
||||
godot_icall_Array_CopyTo(GetPtr(), array, index);
|
||||
godot_icall_Array_CopyTo(ref NativeValue, array, index);
|
||||
}
|
||||
|
||||
// IEnumerable
|
||||
|
@ -268,73 +255,71 @@ namespace Godot.Collections
|
|||
/// <returns>A string representation of this array.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return godot_icall_Array_ToString(GetPtr());
|
||||
return godot_icall_Array_ToString(ref NativeValue);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static IntPtr godot_icall_Array_Ctor();
|
||||
internal static extern void godot_icall_Array_Ctor(out godot_array dest);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static IntPtr godot_icall_Array_Ctor_MonoArray(System.Array array);
|
||||
internal static extern void godot_icall_Array_Ctor_MonoArray(System.Array array, out godot_array dest);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Array_Dtor(IntPtr ptr);
|
||||
internal static extern void godot_icall_Array_At(ref godot_array ptr, int index, out godot_variant elem);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static object godot_icall_Array_At(IntPtr ptr, int index);
|
||||
internal static extern void godot_icall_Array_SetAt(ref godot_array ptr, int index, object value);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static object godot_icall_Array_At_Generic(IntPtr ptr, int index, int elemTypeEncoding, IntPtr elemTypeClass);
|
||||
internal static extern int godot_icall_Array_Count(ref godot_array ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Array_SetAt(IntPtr ptr, int index, object value);
|
||||
internal static extern int godot_icall_Array_Add(ref godot_array ptr, object item);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static int godot_icall_Array_Count(IntPtr ptr);
|
||||
internal static extern void godot_icall_Array_Clear(ref godot_array ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static int godot_icall_Array_Add(IntPtr ptr, object item);
|
||||
internal static extern void godot_icall_Array_Concatenate(ref godot_array left, ref godot_array right, out godot_array dest);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Array_Clear(IntPtr ptr);
|
||||
internal static extern bool godot_icall_Array_Contains(ref godot_array ptr, object item);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static IntPtr godot_icall_Array_Concatenate(IntPtr left, IntPtr right);
|
||||
internal static extern void godot_icall_Array_CopyTo(ref godot_array ptr, System.Array array, int arrayIndex);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static bool godot_icall_Array_Contains(IntPtr ptr, object item);
|
||||
internal static extern void godot_icall_Array_Duplicate(ref godot_array ptr, bool deep, out godot_array dest);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Array_CopyTo(IntPtr ptr, System.Array array, int arrayIndex);
|
||||
internal static extern int godot_icall_Array_IndexOf(ref godot_array ptr, object item);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static IntPtr godot_icall_Array_Duplicate(IntPtr ptr, bool deep);
|
||||
internal static extern void godot_icall_Array_Insert(ref godot_array ptr, int index, object item);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static int godot_icall_Array_IndexOf(IntPtr ptr, object item);
|
||||
internal static extern bool godot_icall_Array_Remove(ref godot_array ptr, object item);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Array_Insert(IntPtr ptr, int index, object item);
|
||||
internal static extern void godot_icall_Array_RemoveAt(ref godot_array ptr, int index);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static bool godot_icall_Array_Remove(IntPtr ptr, object item);
|
||||
internal static extern Error godot_icall_Array_Resize(ref godot_array ptr, int newSize);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Array_RemoveAt(IntPtr ptr, int index);
|
||||
internal static extern Error godot_icall_Array_Shuffle(ref godot_array ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static Error godot_icall_Array_Resize(IntPtr ptr, int newSize);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static Error godot_icall_Array_Shuffle(IntPtr ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Array_Generic_GetElementTypeInfo(Type elemType, out int elemTypeEncoding, out IntPtr elemTypeClass);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static string godot_icall_Array_ToString(IntPtr ptr);
|
||||
internal static extern string godot_icall_Array_ToString(ref godot_array ptr);
|
||||
}
|
||||
|
||||
internal interface IGenericGodotArray
|
||||
{
|
||||
Array UnderlyingArray { get; }
|
||||
Type TypeOfElements { get; }
|
||||
}
|
||||
|
||||
// TODO: Now we should be able to avoid boxing
|
||||
/// <summary>
|
||||
/// Typed wrapper around Godot's Array class, an array of Variant
|
||||
/// typed elements allocated in the engine in C++. Useful when
|
||||
|
@ -342,24 +327,27 @@ namespace Godot.Collections
|
|||
/// such as arrays or <see cref="List{T}"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the array.</typeparam>
|
||||
public class Array<T> : IList<T>, ICollection<T>, IEnumerable<T>
|
||||
[SuppressMessage("ReSharper", "RedundantExtendsListEntry")]
|
||||
public sealed class Array<T> : IList<T>, ICollection<T>, IEnumerable<T>, IGenericGodotArray
|
||||
{
|
||||
Array objectArray;
|
||||
private readonly Array _underlyingArray;
|
||||
|
||||
internal static int elemTypeEncoding;
|
||||
internal static IntPtr elemTypeClass;
|
||||
// ReSharper disable StaticMemberInGenericType
|
||||
// Warning is about unique static fields being created for each generic type combination:
|
||||
// https://www.jetbrains.com/help/resharper/StaticMemberInGenericType.html
|
||||
// In our case this is exactly what we want.
|
||||
private static readonly Type TypeOfElements = typeof(T);
|
||||
// ReSharper restore StaticMemberInGenericType
|
||||
|
||||
static Array()
|
||||
{
|
||||
Array.godot_icall_Array_Generic_GetElementTypeInfo(typeof(T), out elemTypeEncoding, out elemTypeClass);
|
||||
}
|
||||
Array IGenericGodotArray.UnderlyingArray => _underlyingArray;
|
||||
Type IGenericGodotArray.TypeOfElements => TypeOfElements;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new empty <see cref="Array{T}"/>.
|
||||
/// </summary>
|
||||
public Array()
|
||||
{
|
||||
objectArray = new Array();
|
||||
_underlyingArray = new Array();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -372,7 +360,7 @@ namespace Godot.Collections
|
|||
if (collection == null)
|
||||
throw new NullReferenceException($"Parameter '{nameof(collection)} cannot be null.'");
|
||||
|
||||
objectArray = new Array(collection);
|
||||
_underlyingArray = new Array(collection);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -386,7 +374,8 @@ namespace Godot.Collections
|
|||
{
|
||||
throw new NullReferenceException($"Parameter '{nameof(array)} cannot be null.'");
|
||||
}
|
||||
objectArray = new Array(array);
|
||||
|
||||
_underlyingArray = new Array(array);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -395,23 +384,12 @@ namespace Godot.Collections
|
|||
/// <param name="array">The untyped array to construct from.</param>
|
||||
public Array(Array array)
|
||||
{
|
||||
objectArray = array;
|
||||
_underlyingArray = array;
|
||||
}
|
||||
|
||||
internal Array(IntPtr handle)
|
||||
{
|
||||
objectArray = new Array(handle);
|
||||
}
|
||||
|
||||
internal Array(ArraySafeHandle handle)
|
||||
{
|
||||
objectArray = new Array(handle);
|
||||
}
|
||||
|
||||
internal IntPtr GetPtr()
|
||||
{
|
||||
return objectArray.GetPtr();
|
||||
}
|
||||
// Explicit name to make it very clear
|
||||
internal static Array<T> CreateTakingOwnershipOfDisposableValue(godot_array nativeValueToOwn)
|
||||
=> new Array<T>(Array.CreateTakingOwnershipOfDisposableValue(nativeValueToOwn));
|
||||
|
||||
/// <summary>
|
||||
/// Converts this typed <see cref="Array{T}"/> to an untyped <see cref="Array"/>.
|
||||
|
@ -419,7 +397,7 @@ namespace Godot.Collections
|
|||
/// <param name="from">The typed array to convert.</param>
|
||||
public static explicit operator Array(Array<T> from)
|
||||
{
|
||||
return from.objectArray;
|
||||
return from._underlyingArray;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -429,7 +407,7 @@ namespace Godot.Collections
|
|||
/// <returns>A new Godot Array.</returns>
|
||||
public Array<T> Duplicate(bool deep = false)
|
||||
{
|
||||
return new Array<T>(objectArray.Duplicate(deep));
|
||||
return new Array<T>(_underlyingArray.Duplicate(deep));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -439,7 +417,7 @@ namespace Godot.Collections
|
|||
/// <returns><see cref="Error.Ok"/> if successful, or an error code.</returns>
|
||||
public Error Resize(int newSize)
|
||||
{
|
||||
return objectArray.Resize(newSize);
|
||||
return _underlyingArray.Resize(newSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -447,7 +425,7 @@ namespace Godot.Collections
|
|||
/// </summary>
|
||||
public void Shuffle()
|
||||
{
|
||||
objectArray.Shuffle();
|
||||
_underlyingArray.Shuffle();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -458,7 +436,7 @@ namespace Godot.Collections
|
|||
/// <returns>A new Godot Array with the contents of both arrays.</returns>
|
||||
public static Array<T> operator +(Array<T> left, Array<T> right)
|
||||
{
|
||||
return new Array<T>(left.objectArray + right.objectArray);
|
||||
return new Array<T>(left._underlyingArray + right._underlyingArray);
|
||||
}
|
||||
|
||||
// IList<T>
|
||||
|
@ -469,8 +447,16 @@ namespace Godot.Collections
|
|||
/// <value>The value at the given index.</value>
|
||||
public T this[int index]
|
||||
{
|
||||
get { return (T)Array.godot_icall_Array_At_Generic(GetPtr(), index, elemTypeEncoding, elemTypeClass); }
|
||||
set { objectArray[index] = value; }
|
||||
get
|
||||
{
|
||||
Array.godot_icall_Array_At(ref _underlyingArray.NativeValue, index, out godot_variant elem);
|
||||
unsafe
|
||||
{
|
||||
using (elem)
|
||||
return (T)Marshaling.variant_to_mono_object_of_type(&elem, TypeOfElements);
|
||||
}
|
||||
}
|
||||
set => _underlyingArray[index] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -481,7 +467,7 @@ namespace Godot.Collections
|
|||
/// <returns>The index of the item, or -1 if not found.</returns>
|
||||
public int IndexOf(T item)
|
||||
{
|
||||
return objectArray.IndexOf(item);
|
||||
return _underlyingArray.IndexOf(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -494,7 +480,7 @@ namespace Godot.Collections
|
|||
/// <param name="item">The item to insert.</param>
|
||||
public void Insert(int index, T item)
|
||||
{
|
||||
objectArray.Insert(index, item);
|
||||
_underlyingArray.Insert(index, item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -503,7 +489,7 @@ namespace Godot.Collections
|
|||
/// <param name="index">The index of the element to remove.</param>
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
objectArray.RemoveAt(index);
|
||||
_underlyingArray.RemoveAt(index);
|
||||
}
|
||||
|
||||
// ICollection<T>
|
||||
|
@ -513,10 +499,7 @@ namespace Godot.Collections
|
|||
/// This is also known as the size or length of the array.
|
||||
/// </summary>
|
||||
/// <returns>The number of elements.</returns>
|
||||
public int Count
|
||||
{
|
||||
get { return objectArray.Count; }
|
||||
}
|
||||
public int Count => _underlyingArray.Count;
|
||||
|
||||
bool ICollection<T>.IsReadOnly => false;
|
||||
|
||||
|
@ -528,7 +511,7 @@ namespace Godot.Collections
|
|||
/// <returns>The new size after adding the item.</returns>
|
||||
public void Add(T item)
|
||||
{
|
||||
objectArray.Add(item);
|
||||
_underlyingArray.Add(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -536,7 +519,7 @@ namespace Godot.Collections
|
|||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
objectArray.Clear();
|
||||
_underlyingArray.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -546,7 +529,7 @@ namespace Godot.Collections
|
|||
/// <returns>Whether or not this array contains the given item.</returns>
|
||||
public bool Contains(T item)
|
||||
{
|
||||
return objectArray.Contains(item);
|
||||
return _underlyingArray.Contains(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -563,17 +546,14 @@ namespace Godot.Collections
|
|||
if (arrayIndex < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(arrayIndex), "Number was less than the array's lower bound in the first dimension.");
|
||||
|
||||
// TODO This may be quite slow because every element access is an internal call.
|
||||
// It could be moved entirely to an internal call if we find out how to do the cast there.
|
||||
|
||||
int count = objectArray.Count;
|
||||
int count = _underlyingArray.Count;
|
||||
|
||||
if (array.Length < (arrayIndex + count))
|
||||
throw new ArgumentException("Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
array[arrayIndex] = (T)this[i];
|
||||
array[arrayIndex] = this[i];
|
||||
arrayIndex++;
|
||||
}
|
||||
}
|
||||
|
@ -586,7 +566,7 @@ namespace Godot.Collections
|
|||
/// <returns>A bool indicating success or failure.</returns>
|
||||
public bool Remove(T item)
|
||||
{
|
||||
return Array.godot_icall_Array_Remove(GetPtr(), item);
|
||||
return Array.godot_icall_Array_Remove(ref _underlyingArray.NativeValue, item);
|
||||
}
|
||||
|
||||
// IEnumerable<T>
|
||||
|
@ -597,23 +577,20 @@ namespace Godot.Collections
|
|||
/// <returns>An enumerator.</returns>
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
int count = objectArray.Count;
|
||||
int count = _underlyingArray.Count;
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
yield return (T)this[i];
|
||||
yield return this[i];
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
/// <summary>
|
||||
/// Converts this <see cref="Array{T}"/> to a string.
|
||||
/// </summary>
|
||||
/// <returns>A string representation of this array.</returns>
|
||||
public override string ToString() => objectArray.ToString();
|
||||
public override string ToString() => _underlyingArray.ToString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -727,7 +727,7 @@ namespace Godot
|
|||
/// (in the YXZ convention: when *composing*, first Y, then X, and Z last),
|
||||
/// given in the vector format as (X angle, Y angle, Z angle).
|
||||
///
|
||||
/// Consider using the <see cref="Basis(Quaternion)"/> constructor instead, which
|
||||
/// Consider using the <see cref="Basis(Godot.Quaternion)"/> constructor instead, which
|
||||
/// uses a <see cref="Godot.Quaternion"/> quaternion instead of Euler angles.
|
||||
/// </summary>
|
||||
/// <param name="eulerYXZ">The Euler angles to create the basis from.</param>
|
||||
|
|
|
@ -4,11 +4,53 @@ using System.Diagnostics;
|
|||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
namespace Godot
|
||||
{
|
||||
internal static class DelegateUtils
|
||||
{
|
||||
// TODO: Move somewhere else once we need to for things other than delegates
|
||||
internal static void FreeGCHandle(IntPtr delegateGCHandle)
|
||||
=> GCHandle.FromIntPtr(delegateGCHandle).Free();
|
||||
|
||||
internal static bool DelegateEquals(IntPtr delegateGCHandleA, IntPtr delegateGCHandleB)
|
||||
{
|
||||
var @delegateA = (Delegate)GCHandle.FromIntPtr(delegateGCHandleA).Target;
|
||||
var @delegateB = (Delegate)GCHandle.FromIntPtr(delegateGCHandleB).Target;
|
||||
return @delegateA == @delegateB;
|
||||
}
|
||||
|
||||
internal static unsafe void InvokeWithVariantArgs(IntPtr delegateGCHandle, godot_variant** args, uint argc, godot_variant* ret)
|
||||
{
|
||||
// TODO: Optimize
|
||||
var @delegate = (Delegate)GCHandle.FromIntPtr(delegateGCHandle).Target;
|
||||
var managedArgs = new object[argc];
|
||||
|
||||
var parameterInfos = @delegate.Method.GetParameters();
|
||||
|
||||
var paramsLength = parameterInfos.Length;
|
||||
|
||||
if (argc != paramsLength)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"The delegate expects {paramsLength} arguments, but received {argc}.");
|
||||
}
|
||||
|
||||
for (uint i = 0; i < argc; i++)
|
||||
{
|
||||
managedArgs[i] = Marshaling.variant_to_mono_object_of_type(
|
||||
args[i], parameterInfos[i].ParameterType);
|
||||
}
|
||||
|
||||
object invokeRet = @delegate.DynamicInvoke(managedArgs);
|
||||
|
||||
*ret = Marshaling.mono_object_to_variant(invokeRet);
|
||||
}
|
||||
|
||||
// TODO: Check if we should be using BindingFlags.DeclaredOnly (would give better reflection performance).
|
||||
|
||||
private enum TargetKind : uint
|
||||
{
|
||||
Static,
|
||||
|
@ -16,7 +58,10 @@ namespace Godot
|
|||
CompilerGenerated
|
||||
}
|
||||
|
||||
internal static bool TrySerializeDelegate(Delegate @delegate, Collections.Array serializedData)
|
||||
internal static bool TrySerializeDelegateWithGCHandle(IntPtr delegateGCHandle, Collections.Array serializedData)
|
||||
=> TrySerializeDelegate((Delegate)GCHandle.FromIntPtr(delegateGCHandle).Target, serializedData);
|
||||
|
||||
private static bool TrySerializeDelegate(Delegate @delegate, Collections.Array serializedData)
|
||||
{
|
||||
if (@delegate is MulticastDelegate multicastDelegate)
|
||||
{
|
||||
|
@ -72,12 +117,14 @@ namespace Godot
|
|||
return true;
|
||||
}
|
||||
}
|
||||
// ReSharper disable once RedundantNameQualifier
|
||||
case Godot.Object godotObject:
|
||||
{
|
||||
using (var stream = new MemoryStream())
|
||||
using (var writer = new BinaryWriter(stream))
|
||||
{
|
||||
writer.Write((ulong)TargetKind.GodotObject);
|
||||
// ReSharper disable once RedundantCast
|
||||
writer.Write((ulong)godotObject.GetInstanceId());
|
||||
|
||||
SerializeType(writer, @delegate.GetType());
|
||||
|
@ -93,7 +140,7 @@ namespace Godot
|
|||
{
|
||||
Type targetType = target.GetType();
|
||||
|
||||
if (targetType.GetCustomAttribute(typeof(CompilerGeneratedAttribute), true) != null)
|
||||
if (targetType.IsDefined(typeof(CompilerGeneratedAttribute), true))
|
||||
{
|
||||
// Compiler generated. Probably a closure. Try to serialize it.
|
||||
|
||||
|
@ -213,6 +260,13 @@ namespace Godot
|
|||
}
|
||||
}
|
||||
|
||||
private static bool TryDeserializeDelegateWithGCHandle(Collections.Array serializedData, out IntPtr delegateGCHandle)
|
||||
{
|
||||
bool res = TryDeserializeDelegate(serializedData, out Delegate @delegate);
|
||||
delegateGCHandle = GCHandle.ToIntPtr(GCHandle.Alloc(@delegate));
|
||||
return res;
|
||||
}
|
||||
|
||||
private static bool TryDeserializeDelegate(Collections.Array serializedData, out Delegate @delegate)
|
||||
{
|
||||
if (serializedData.Count == 1)
|
||||
|
@ -276,6 +330,7 @@ namespace Godot
|
|||
case TargetKind.GodotObject:
|
||||
{
|
||||
ulong objectId = reader.ReadUInt64();
|
||||
// ReSharper disable once RedundantNameQualifier
|
||||
Godot.Object godotObject = GD.InstanceFromId(objectId);
|
||||
if (godotObject == null)
|
||||
return false;
|
||||
|
|
|
@ -2,48 +2,28 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Godot.NativeInterop;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Godot.Collections
|
||||
{
|
||||
class DictionarySafeHandle : SafeHandle
|
||||
{
|
||||
public DictionarySafeHandle(IntPtr handle) : base(IntPtr.Zero, true)
|
||||
{
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
public override bool IsInvalid
|
||||
{
|
||||
get { return handle == IntPtr.Zero; }
|
||||
}
|
||||
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
Dictionary.godot_icall_Dictionary_Dtor(handle);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper around Godot's Dictionary class, a dictionary of Variant
|
||||
/// typed elements allocated in the engine in C++. Useful when
|
||||
/// interfacing with the engine.
|
||||
/// </summary>
|
||||
public class Dictionary :
|
||||
public sealed class Dictionary :
|
||||
IDictionary,
|
||||
IDisposable
|
||||
{
|
||||
DictionarySafeHandle safeHandle;
|
||||
bool disposed = false;
|
||||
internal godot_dictionary NativeValue;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new empty <see cref="Dictionary"/>.
|
||||
/// </summary>
|
||||
public Dictionary()
|
||||
{
|
||||
safeHandle = new DictionarySafeHandle(godot_icall_Dictionary_Ctor());
|
||||
godot_icall_Dictionary_Ctor(out NativeValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -60,22 +40,18 @@ namespace Godot.Collections
|
|||
Add(entry.Key, entry.Value);
|
||||
}
|
||||
|
||||
internal Dictionary(DictionarySafeHandle handle)
|
||||
private Dictionary(godot_dictionary nativeValueToOwn)
|
||||
{
|
||||
safeHandle = handle;
|
||||
NativeValue = nativeValueToOwn;
|
||||
}
|
||||
|
||||
internal Dictionary(IntPtr handle)
|
||||
{
|
||||
safeHandle = new DictionarySafeHandle(handle);
|
||||
}
|
||||
// Explicit name to make it very clear
|
||||
internal static Dictionary CreateTakingOwnershipOfDisposableValue(godot_dictionary nativeValueToOwn)
|
||||
=> new Dictionary(nativeValueToOwn);
|
||||
|
||||
internal IntPtr GetPtr()
|
||||
~Dictionary()
|
||||
{
|
||||
if (disposed)
|
||||
throw new ObjectDisposedException(GetType().FullName);
|
||||
|
||||
return safeHandle.DangerousGetHandle();
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -83,16 +59,14 @@ namespace Godot.Collections
|
|||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (disposed)
|
||||
return;
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
if (safeHandle != null)
|
||||
{
|
||||
safeHandle.Dispose();
|
||||
safeHandle = null;
|
||||
}
|
||||
|
||||
disposed = true;
|
||||
public void Dispose(bool disposing)
|
||||
{
|
||||
// Always dispose `NativeValue` even if disposing is true
|
||||
NativeValue.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -102,7 +76,9 @@ namespace Godot.Collections
|
|||
/// <returns>A new Godot Dictionary.</returns>
|
||||
public Dictionary Duplicate(bool deep = false)
|
||||
{
|
||||
return new Dictionary(godot_icall_Dictionary_Duplicate(GetPtr(), deep));
|
||||
godot_dictionary newDictionary;
|
||||
godot_icall_Dictionary_Duplicate(ref NativeValue, deep, out newDictionary);
|
||||
return CreateTakingOwnershipOfDisposableValue(newDictionary);
|
||||
}
|
||||
|
||||
// IDictionary
|
||||
|
@ -114,8 +90,9 @@ namespace Godot.Collections
|
|||
{
|
||||
get
|
||||
{
|
||||
IntPtr handle = godot_icall_Dictionary_Keys(GetPtr());
|
||||
return new Array(new ArraySafeHandle(handle));
|
||||
godot_array keysArray;
|
||||
godot_icall_Dictionary_Keys(ref NativeValue, out keysArray);
|
||||
return Array.CreateTakingOwnershipOfDisposableValue(keysArray);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,16 +103,19 @@ namespace Godot.Collections
|
|||
{
|
||||
get
|
||||
{
|
||||
IntPtr handle = godot_icall_Dictionary_Values(GetPtr());
|
||||
return new Array(new ArraySafeHandle(handle));
|
||||
godot_array valuesArray;
|
||||
godot_icall_Dictionary_Values(ref NativeValue, out valuesArray);
|
||||
return Array.CreateTakingOwnershipOfDisposableValue(valuesArray);
|
||||
}
|
||||
}
|
||||
|
||||
private (Array keys, Array values, int count) GetKeyValuePairs()
|
||||
{
|
||||
int count = godot_icall_Dictionary_KeyValuePairs(GetPtr(), out IntPtr keysHandle, out IntPtr valuesHandle);
|
||||
Array keys = new Array(new ArraySafeHandle(keysHandle));
|
||||
Array values = new Array(new ArraySafeHandle(valuesHandle));
|
||||
godot_array keysArray;
|
||||
godot_array valuesArray;
|
||||
int count = godot_icall_Dictionary_KeyValuePairs(ref NativeValue, out keysArray, out valuesArray);
|
||||
var keys = Array.CreateTakingOwnershipOfDisposableValue(keysArray);
|
||||
var values = Array.CreateTakingOwnershipOfDisposableValue(valuesArray);
|
||||
return (keys, values, count);
|
||||
}
|
||||
|
||||
|
@ -149,8 +129,16 @@ namespace Godot.Collections
|
|||
/// <value>The object at the given <paramref name="key"/>.</value>
|
||||
public object this[object key]
|
||||
{
|
||||
get => godot_icall_Dictionary_GetValue(GetPtr(), key);
|
||||
set => godot_icall_Dictionary_SetValue(GetPtr(), key, value);
|
||||
get
|
||||
{
|
||||
godot_icall_Dictionary_GetValue(ref NativeValue, key, out godot_variant value);
|
||||
unsafe
|
||||
{
|
||||
using (value)
|
||||
return Marshaling.variant_to_mono_object(&value);
|
||||
}
|
||||
}
|
||||
set => godot_icall_Dictionary_SetValue(ref NativeValue, key, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -159,19 +147,19 @@ namespace Godot.Collections
|
|||
/// </summary>
|
||||
/// <param name="key">The key at which to add the object.</param>
|
||||
/// <param name="value">The object to add.</param>
|
||||
public void Add(object key, object value) => godot_icall_Dictionary_Add(GetPtr(), key, value);
|
||||
public void Add(object key, object value) => godot_icall_Dictionary_Add(ref NativeValue, key, value);
|
||||
|
||||
/// <summary>
|
||||
/// Erases all items from this <see cref="Dictionary"/>.
|
||||
/// </summary>
|
||||
public void Clear() => godot_icall_Dictionary_Clear(GetPtr());
|
||||
public void Clear() => godot_icall_Dictionary_Clear(ref NativeValue);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if this <see cref="Dictionary"/> contains the given key.
|
||||
/// </summary>
|
||||
/// <param name="key">The key to look for.</param>
|
||||
/// <returns>Whether or not this dictionary contains the given key.</returns>
|
||||
public bool Contains(object key) => godot_icall_Dictionary_ContainsKey(GetPtr(), key);
|
||||
public bool Contains(object key) => godot_icall_Dictionary_ContainsKey(ref NativeValue, key);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an enumerator for this <see cref="Dictionary"/>.
|
||||
|
@ -183,7 +171,7 @@ namespace Godot.Collections
|
|||
/// Removes an element from this <see cref="Dictionary"/> by key.
|
||||
/// </summary>
|
||||
/// <param name="key">The key of the element to remove.</param>
|
||||
public void Remove(object key) => godot_icall_Dictionary_RemoveKey(GetPtr(), key);
|
||||
public void Remove(object key) => godot_icall_Dictionary_RemoveKey(ref NativeValue, key);
|
||||
|
||||
// ICollection
|
||||
|
||||
|
@ -196,7 +184,7 @@ namespace Godot.Collections
|
|||
/// This is also known as the size or length of the dictionary.
|
||||
/// </summary>
|
||||
/// <returns>The number of elements.</returns>
|
||||
public int Count => godot_icall_Dictionary_Count(GetPtr());
|
||||
public int Count => godot_icall_Dictionary_Count(ref NativeValue);
|
||||
|
||||
/// <summary>
|
||||
/// Copies the elements of this <see cref="Dictionary"/> to the given
|
||||
|
@ -260,7 +248,7 @@ namespace Godot.Collections
|
|||
private void UpdateEntry()
|
||||
{
|
||||
dirty = false;
|
||||
godot_icall_Dictionary_KeyValuePairAt(dictionary.GetPtr(), index, out object key, out object value);
|
||||
godot_icall_Dictionary_KeyValuePairAt(ref dictionary.NativeValue, index, out object key, out object value);
|
||||
entry = new DictionaryEntry(key, value);
|
||||
}
|
||||
|
||||
|
@ -288,73 +276,70 @@ namespace Godot.Collections
|
|||
/// <returns>A string representation of this dictionary.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return godot_icall_Dictionary_ToString(GetPtr());
|
||||
return godot_icall_Dictionary_ToString(ref NativeValue);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static IntPtr godot_icall_Dictionary_Ctor();
|
||||
internal static extern void godot_icall_Dictionary_Ctor(out godot_dictionary dest);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Dictionary_Dtor(IntPtr ptr);
|
||||
internal static extern void godot_icall_Dictionary_GetValue(ref godot_dictionary ptr, object key, out godot_variant value);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static object godot_icall_Dictionary_GetValue(IntPtr ptr, object key);
|
||||
internal static extern void godot_icall_Dictionary_SetValue(ref godot_dictionary ptr, object key, object value);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static object godot_icall_Dictionary_GetValue_Generic(IntPtr ptr, object key, int valTypeEncoding, IntPtr valTypeClass);
|
||||
internal static extern void godot_icall_Dictionary_Keys(ref godot_dictionary ptr, out godot_array dest);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Dictionary_SetValue(IntPtr ptr, object key, object value);
|
||||
internal static extern void godot_icall_Dictionary_Values(ref godot_dictionary ptr, out godot_array dest);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static IntPtr godot_icall_Dictionary_Keys(IntPtr ptr);
|
||||
internal static extern int godot_icall_Dictionary_KeyValuePairs(ref godot_dictionary ptr, out godot_array keys, out godot_array values);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static IntPtr godot_icall_Dictionary_Values(IntPtr ptr);
|
||||
internal static extern void godot_icall_Dictionary_KeyValuePairAt(ref godot_dictionary ptr, int index, out object key, out object value);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static int godot_icall_Dictionary_Count(IntPtr ptr);
|
||||
internal static extern void godot_icall_Dictionary_Add(ref godot_dictionary ptr, object key, object value);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static int godot_icall_Dictionary_KeyValuePairs(IntPtr ptr, out IntPtr keys, out IntPtr values);
|
||||
internal static extern int godot_icall_Dictionary_Count(ref godot_dictionary ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Dictionary_KeyValuePairAt(IntPtr ptr, int index, out object key, out object value);
|
||||
internal static extern void godot_icall_Dictionary_Clear(ref godot_dictionary ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Dictionary_Add(IntPtr ptr, object key, object value);
|
||||
internal static extern bool godot_icall_Dictionary_Contains(ref godot_dictionary ptr, object key, object value);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Dictionary_Clear(IntPtr ptr);
|
||||
internal static extern bool godot_icall_Dictionary_ContainsKey(ref godot_dictionary ptr, object key);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static bool godot_icall_Dictionary_Contains(IntPtr ptr, object key, object value);
|
||||
internal static extern void godot_icall_Dictionary_Duplicate(ref godot_dictionary ptr, bool deep, out godot_dictionary dest);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static bool godot_icall_Dictionary_ContainsKey(IntPtr ptr, object key);
|
||||
internal static extern bool godot_icall_Dictionary_RemoveKey(ref godot_dictionary ptr, object key);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static IntPtr godot_icall_Dictionary_Duplicate(IntPtr ptr, bool deep);
|
||||
internal static extern bool godot_icall_Dictionary_Remove(ref godot_dictionary ptr, object key, object value);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static bool godot_icall_Dictionary_RemoveKey(IntPtr ptr, object key);
|
||||
internal static extern bool godot_icall_Dictionary_TryGetValue(ref godot_dictionary ptr, object key, out godot_variant value);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static bool godot_icall_Dictionary_Remove(IntPtr ptr, object key, object value);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static bool godot_icall_Dictionary_TryGetValue(IntPtr ptr, object key, out object value);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static bool godot_icall_Dictionary_TryGetValue_Generic(IntPtr ptr, object key, out object value, int valTypeEncoding, IntPtr valTypeClass);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Dictionary_Generic_GetValueTypeInfo(Type valueType, out int valTypeEncoding, out IntPtr valTypeClass);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static string godot_icall_Dictionary_ToString(IntPtr ptr);
|
||||
internal static extern string godot_icall_Dictionary_ToString(ref godot_dictionary ptr);
|
||||
}
|
||||
|
||||
internal interface IGenericGodotDictionary
|
||||
{
|
||||
Dictionary UnderlyingDictionary { get; }
|
||||
Type TypeOfKeys { get; }
|
||||
Type TypeOfValues { get; }
|
||||
}
|
||||
|
||||
// TODO: Now we should be able to avoid boxing
|
||||
|
||||
/// <summary>
|
||||
/// Typed wrapper around Godot's Dictionary class, a dictionary of Variant
|
||||
/// typed elements allocated in the engine in C++. Useful when
|
||||
|
@ -363,25 +348,30 @@ namespace Godot.Collections
|
|||
/// </summary>
|
||||
/// <typeparam name="TKey">The type of the dictionary's keys.</typeparam>
|
||||
/// <typeparam name="TValue">The type of the dictionary's values.</typeparam>
|
||||
public class Dictionary<TKey, TValue> :
|
||||
IDictionary<TKey, TValue>
|
||||
public sealed class Dictionary<TKey, TValue> :
|
||||
IDictionary<TKey, TValue>, IGenericGodotDictionary
|
||||
{
|
||||
private readonly Dictionary objectDict;
|
||||
private readonly Dictionary _underlyingDict;
|
||||
|
||||
internal static int valTypeEncoding;
|
||||
internal static IntPtr valTypeClass;
|
||||
// ReSharper disable StaticMemberInGenericType
|
||||
// Warning is about unique static fields being created for each generic type combination:
|
||||
// https://www.jetbrains.com/help/resharper/StaticMemberInGenericType.html
|
||||
// In our case this is exactly what we want.
|
||||
private static readonly Type TypeOfKeys = typeof(TKey);
|
||||
|
||||
static Dictionary()
|
||||
{
|
||||
Dictionary.godot_icall_Dictionary_Generic_GetValueTypeInfo(typeof(TValue), out valTypeEncoding, out valTypeClass);
|
||||
}
|
||||
private static readonly Type TypeOfValues = typeof(TValue);
|
||||
// ReSharper restore StaticMemberInGenericType
|
||||
|
||||
Dictionary IGenericGodotDictionary.UnderlyingDictionary => _underlyingDict;
|
||||
Type IGenericGodotDictionary.TypeOfKeys => TypeOfKeys;
|
||||
Type IGenericGodotDictionary.TypeOfValues => TypeOfValues;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new empty <see cref="Dictionary{TKey, TValue}"/>.
|
||||
/// </summary>
|
||||
public Dictionary()
|
||||
{
|
||||
objectDict = new Dictionary();
|
||||
_underlyingDict = new Dictionary();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -391,19 +381,13 @@ namespace Godot.Collections
|
|||
/// <returns>A new Godot Dictionary.</returns>
|
||||
public Dictionary(IDictionary<TKey, TValue> dictionary)
|
||||
{
|
||||
objectDict = new Dictionary();
|
||||
_underlyingDict = new Dictionary();
|
||||
|
||||
if (dictionary == null)
|
||||
throw new NullReferenceException($"Parameter '{nameof(dictionary)} cannot be null.'");
|
||||
|
||||
// TODO: Can be optimized
|
||||
|
||||
IntPtr godotDictionaryPtr = GetPtr();
|
||||
|
||||
foreach (KeyValuePair<TKey, TValue> entry in dictionary)
|
||||
{
|
||||
Dictionary.godot_icall_Dictionary_Add(godotDictionaryPtr, entry.Key, entry.Value);
|
||||
}
|
||||
Add(entry.Key, entry.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -413,18 +397,12 @@ namespace Godot.Collections
|
|||
/// <returns>A new Godot Dictionary.</returns>
|
||||
public Dictionary(Dictionary dictionary)
|
||||
{
|
||||
objectDict = dictionary;
|
||||
_underlyingDict = dictionary;
|
||||
}
|
||||
|
||||
internal Dictionary(IntPtr handle)
|
||||
{
|
||||
objectDict = new Dictionary(handle);
|
||||
}
|
||||
|
||||
internal Dictionary(DictionarySafeHandle handle)
|
||||
{
|
||||
objectDict = new Dictionary(handle);
|
||||
}
|
||||
// Explicit name to make it very clear
|
||||
internal static Dictionary<TKey, TValue> CreateTakingOwnershipOfDisposableValue(godot_dictionary nativeValueToOwn)
|
||||
=> new Dictionary<TKey, TValue>(Dictionary.CreateTakingOwnershipOfDisposableValue(nativeValueToOwn));
|
||||
|
||||
/// <summary>
|
||||
/// Converts this typed <see cref="Dictionary{TKey, TValue}"/> to an untyped <see cref="Dictionary"/>.
|
||||
|
@ -432,12 +410,7 @@ namespace Godot.Collections
|
|||
/// <param name="from">The typed dictionary to convert.</param>
|
||||
public static explicit operator Dictionary(Dictionary<TKey, TValue> from)
|
||||
{
|
||||
return from.objectDict;
|
||||
}
|
||||
|
||||
internal IntPtr GetPtr()
|
||||
{
|
||||
return objectDict.GetPtr();
|
||||
return from._underlyingDict;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -447,7 +420,7 @@ namespace Godot.Collections
|
|||
/// <returns>A new Godot Dictionary.</returns>
|
||||
public Dictionary<TKey, TValue> Duplicate(bool deep = false)
|
||||
{
|
||||
return new Dictionary<TKey, TValue>(objectDict.Duplicate(deep));
|
||||
return new Dictionary<TKey, TValue>(_underlyingDict.Duplicate(deep));
|
||||
}
|
||||
|
||||
// IDictionary<TKey, TValue>
|
||||
|
@ -458,8 +431,16 @@ namespace Godot.Collections
|
|||
/// <value>The value at the given <paramref name="key"/>.</value>
|
||||
public TValue this[TKey key]
|
||||
{
|
||||
get { return (TValue)Dictionary.godot_icall_Dictionary_GetValue_Generic(objectDict.GetPtr(), key, valTypeEncoding, valTypeClass); }
|
||||
set { objectDict[key] = value; }
|
||||
get
|
||||
{
|
||||
Dictionary.godot_icall_Dictionary_GetValue(ref _underlyingDict.NativeValue, key, out godot_variant value);
|
||||
unsafe
|
||||
{
|
||||
using (value)
|
||||
return (TValue)Marshaling.variant_to_mono_object_of_type(&value, TypeOfValues);
|
||||
}
|
||||
}
|
||||
set => _underlyingDict[key] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -469,8 +450,9 @@ namespace Godot.Collections
|
|||
{
|
||||
get
|
||||
{
|
||||
IntPtr handle = Dictionary.godot_icall_Dictionary_Keys(objectDict.GetPtr());
|
||||
return new Array<TKey>(new ArraySafeHandle(handle));
|
||||
godot_array keyArray;
|
||||
Dictionary.godot_icall_Dictionary_Keys(ref _underlyingDict.NativeValue, out keyArray);
|
||||
return Array<TKey>.CreateTakingOwnershipOfDisposableValue(keyArray);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -481,14 +463,15 @@ namespace Godot.Collections
|
|||
{
|
||||
get
|
||||
{
|
||||
IntPtr handle = Dictionary.godot_icall_Dictionary_Values(objectDict.GetPtr());
|
||||
return new Array<TValue>(new ArraySafeHandle(handle));
|
||||
godot_array valuesArray;
|
||||
Dictionary.godot_icall_Dictionary_Values(ref _underlyingDict.NativeValue, out valuesArray);
|
||||
return Array<TValue>.CreateTakingOwnershipOfDisposableValue(valuesArray);
|
||||
}
|
||||
}
|
||||
|
||||
private KeyValuePair<TKey, TValue> GetKeyValuePair(int index)
|
||||
{
|
||||
Dictionary.godot_icall_Dictionary_KeyValuePairAt(GetPtr(), index, out object key, out object value);
|
||||
Dictionary.godot_icall_Dictionary_KeyValuePairAt(ref _underlyingDict.NativeValue, index, out object key, out object value);
|
||||
return new KeyValuePair<TKey, TValue>((TKey)key, (TValue)value);
|
||||
}
|
||||
|
||||
|
@ -500,7 +483,7 @@ namespace Godot.Collections
|
|||
/// <param name="value">The object to add.</param>
|
||||
public void Add(TKey key, TValue value)
|
||||
{
|
||||
objectDict.Add(key, value);
|
||||
_underlyingDict.Add(key, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -510,7 +493,7 @@ namespace Godot.Collections
|
|||
/// <returns>Whether or not this dictionary contains the given key.</returns>
|
||||
public bool ContainsKey(TKey key)
|
||||
{
|
||||
return objectDict.Contains(key);
|
||||
return _underlyingDict.Contains(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -519,7 +502,7 @@ namespace Godot.Collections
|
|||
/// <param name="key">The key of the element to remove.</param>
|
||||
public bool Remove(TKey key)
|
||||
{
|
||||
return Dictionary.godot_icall_Dictionary_RemoveKey(GetPtr(), key);
|
||||
return Dictionary.godot_icall_Dictionary_RemoveKey(ref _underlyingDict.NativeValue, key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -530,8 +513,18 @@ namespace Godot.Collections
|
|||
/// <returns>If an object was found for the given <paramref name="key"/>.</returns>
|
||||
public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
|
||||
{
|
||||
bool found = Dictionary.godot_icall_Dictionary_TryGetValue_Generic(GetPtr(), key, out object retValue, valTypeEncoding, valTypeClass);
|
||||
value = found ? (TValue)retValue : default;
|
||||
bool found = Dictionary.godot_icall_Dictionary_TryGetValue(ref _underlyingDict.NativeValue, key, out godot_variant retValue);
|
||||
|
||||
unsafe
|
||||
{
|
||||
using (retValue)
|
||||
{
|
||||
value = found ?
|
||||
(TValue)Marshaling.variant_to_mono_object_of_type(&retValue, TypeOfValues) :
|
||||
default;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
@ -542,16 +535,13 @@ namespace Godot.Collections
|
|||
/// This is also known as the size or length of the dictionary.
|
||||
/// </summary>
|
||||
/// <returns>The number of elements.</returns>
|
||||
public int Count
|
||||
{
|
||||
get { return objectDict.Count; }
|
||||
}
|
||||
public int Count => _underlyingDict.Count;
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => false;
|
||||
|
||||
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
objectDict.Add(item.Key, item.Value);
|
||||
_underlyingDict.Add(item.Key, item.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -559,12 +549,12 @@ namespace Godot.Collections
|
|||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
objectDict.Clear();
|
||||
_underlyingDict.Clear();
|
||||
}
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
return objectDict.Contains(new KeyValuePair<object, object>(item.Key, item.Value));
|
||||
return _underlyingDict.Contains(new KeyValuePair<object, object>(item.Key, item.Value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -595,8 +585,7 @@ namespace Godot.Collections
|
|||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
return Dictionary.godot_icall_Dictionary_Remove(GetPtr(), item.Key, item.Value);
|
||||
;
|
||||
return Dictionary.godot_icall_Dictionary_Remove(ref _underlyingDict.NativeValue, item.Key, item.Value);
|
||||
}
|
||||
|
||||
// IEnumerable<KeyValuePair<TKey, TValue>>
|
||||
|
@ -613,15 +602,12 @@ namespace Godot.Collections
|
|||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
/// <summary>
|
||||
/// Converts this <see cref="Dictionary{TKey, TValue}"/> to a string.
|
||||
/// </summary>
|
||||
/// <returns>A string representation of this dictionary.</returns>
|
||||
public override string ToString() => objectDict.ToString();
|
||||
public override string ToString() => _underlyingDict.ToString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Godot.Collections;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
namespace Godot
|
||||
{
|
||||
|
@ -8,10 +9,12 @@ namespace Godot
|
|||
{
|
||||
public Array<T> GetNodesInGroup<T>(StringName group) where T : class
|
||||
{
|
||||
return new Array<T>(godot_icall_SceneTree_get_nodes_in_group_Generic(Object.GetPtr(this), StringName.GetPtr(group), typeof(T)));
|
||||
godot_array array;
|
||||
godot_icall_SceneTree_get_nodes_in_group_Generic(GetPtr(this), ref group.NativeValue, typeof(T), out array);
|
||||
return Array<T>.CreateTakingOwnershipOfDisposableValue(array);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static IntPtr godot_icall_SceneTree_get_nodes_in_group_Generic(IntPtr obj, IntPtr group, Type elemType);
|
||||
internal static extern void godot_icall_SceneTree_get_nodes_in_group_Generic(IntPtr obj, ref godot_string_name group, Type elemType, out godot_array dest);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ using real_t = System.Single;
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
// TODO: Add comments describing what this class does. It is not obvious.
|
||||
|
||||
|
@ -13,9 +14,10 @@ namespace Godot
|
|||
{
|
||||
public static partial class GD
|
||||
{
|
||||
public static object Bytes2Var(byte[] bytes, bool allowObjects = false)
|
||||
public static unsafe object Bytes2Var(byte[] bytes, bool allowObjects = false)
|
||||
{
|
||||
return godot_icall_GD_bytes2var(bytes, allowObjects);
|
||||
using var varBytes = Marshaling.mono_array_to_PackedByteArray(bytes);
|
||||
return godot_icall_GD_bytes2var(&varBytes, allowObjects);
|
||||
}
|
||||
|
||||
public static object Convert(object what, Variant.Type type)
|
||||
|
@ -180,12 +182,17 @@ namespace Godot
|
|||
|
||||
public static bool TypeExists(StringName type)
|
||||
{
|
||||
return godot_icall_GD_type_exists(StringName.GetPtr(type));
|
||||
return godot_icall_GD_type_exists(ref type.NativeValue);
|
||||
}
|
||||
|
||||
public static byte[] Var2Bytes(object var, bool fullObjects = false)
|
||||
public static unsafe byte[] Var2Bytes(object var, bool fullObjects = false)
|
||||
{
|
||||
return godot_icall_GD_var2bytes(var, fullObjects);
|
||||
godot_packed_byte_array varBytes;
|
||||
godot_icall_GD_var2bytes(var, fullObjects, &varBytes);
|
||||
using (varBytes)
|
||||
{
|
||||
return Marshaling.PackedByteArray_to_mono_array(&varBytes);
|
||||
}
|
||||
}
|
||||
|
||||
public static string Var2Str(object var)
|
||||
|
@ -199,73 +206,73 @@ namespace Godot
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static object godot_icall_GD_bytes2var(byte[] bytes, bool allowObjects);
|
||||
internal static extern unsafe object godot_icall_GD_bytes2var(godot_packed_byte_array* bytes, bool allowObjects);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static object godot_icall_GD_convert(object what, Variant.Type type);
|
||||
internal static extern object godot_icall_GD_convert(object what, Variant.Type type);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static int godot_icall_GD_hash(object var);
|
||||
internal static extern int godot_icall_GD_hash(object var);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static Object godot_icall_GD_instance_from_id(ulong instanceId);
|
||||
internal static extern Object godot_icall_GD_instance_from_id(ulong instanceId);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_GD_print(object[] what);
|
||||
internal static extern void godot_icall_GD_print(object[] what);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_GD_printerr(object[] what);
|
||||
internal static extern void godot_icall_GD_printerr(object[] what);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_GD_printraw(object[] what);
|
||||
internal static extern void godot_icall_GD_printraw(object[] what);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_GD_prints(object[] what);
|
||||
internal static extern void godot_icall_GD_prints(object[] what);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_GD_printt(object[] what);
|
||||
internal static extern void godot_icall_GD_printt(object[] what);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static float godot_icall_GD_randf();
|
||||
internal static extern float godot_icall_GD_randf();
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static uint godot_icall_GD_randi();
|
||||
internal static extern uint godot_icall_GD_randi();
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_GD_randomize();
|
||||
internal static extern void godot_icall_GD_randomize();
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static double godot_icall_GD_randf_range(double from, double to);
|
||||
internal static extern double godot_icall_GD_randf_range(double from, double to);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static int godot_icall_GD_randi_range(int from, int to);
|
||||
internal static extern int godot_icall_GD_randi_range(int from, int to);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static uint godot_icall_GD_rand_seed(ulong seed, out ulong newSeed);
|
||||
internal static extern uint godot_icall_GD_rand_seed(ulong seed, out ulong newSeed);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_GD_seed(ulong seed);
|
||||
internal static extern void godot_icall_GD_seed(ulong seed);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static string godot_icall_GD_str(object[] what);
|
||||
internal static extern string godot_icall_GD_str(object[] what);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static object godot_icall_GD_str2var(string str);
|
||||
internal static extern object godot_icall_GD_str2var(string str);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static bool godot_icall_GD_type_exists(IntPtr type);
|
||||
internal static extern bool godot_icall_GD_type_exists(ref godot_string_name type);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static byte[] godot_icall_GD_var2bytes(object what, bool fullObjects);
|
||||
internal static extern unsafe void godot_icall_GD_var2bytes(object what, bool fullObjects, godot_packed_byte_array* bytes);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static string godot_icall_GD_var2str(object var);
|
||||
internal static extern string godot_icall_GD_var2str(object var);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_GD_pusherror(string type);
|
||||
internal static extern void godot_icall_GD_pusherror(string type);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_GD_pushwarning(string type);
|
||||
internal static extern void godot_icall_GD_pushwarning(string type);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern Variant.Type godot_icall_TypeToVariantType(Type type);
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Godot
|
||||
{
|
||||
static class MarshalUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns <see langword="true"/> if the generic type definition of <paramref name="type"/>
|
||||
/// is <see cref="Godot.Collections.Array{T}"/>; otherwise returns <see langword="false"/>.
|
||||
/// </summary>
|
||||
/// <exception cref="System.InvalidOperationException">
|
||||
/// <paramref name="type"/> is not a generic type. That is, IsGenericType returns false.
|
||||
/// </exception>
|
||||
static bool TypeIsGenericArray(Type type) =>
|
||||
type.GetGenericTypeDefinition() == typeof(Godot.Collections.Array<>);
|
||||
|
||||
/// <summary>
|
||||
/// Returns <see langword="true"/> if the generic type definition of <paramref name="type"/>
|
||||
/// is <see cref="Godot.Collections.Dictionary{TKey, TValue}"/>; otherwise returns <see langword="false"/>.
|
||||
/// </summary>
|
||||
/// <exception cref="System.InvalidOperationException">
|
||||
/// <paramref name="type"/> is not a generic type. That is, IsGenericType returns false.
|
||||
/// </exception>
|
||||
static bool TypeIsGenericDictionary(Type type) =>
|
||||
type.GetGenericTypeDefinition() == typeof(Godot.Collections.Dictionary<,>);
|
||||
|
||||
static bool TypeIsSystemGenericList(Type type) =>
|
||||
type.GetGenericTypeDefinition() == typeof(System.Collections.Generic.List<>);
|
||||
|
||||
static bool TypeIsSystemGenericDictionary(Type type) =>
|
||||
type.GetGenericTypeDefinition() == typeof(System.Collections.Generic.Dictionary<,>);
|
||||
|
||||
static bool TypeIsGenericIEnumerable(Type type) => type.GetGenericTypeDefinition() == typeof(IEnumerable<>);
|
||||
|
||||
static bool TypeIsGenericICollection(Type type) => type.GetGenericTypeDefinition() == typeof(ICollection<>);
|
||||
|
||||
static bool TypeIsGenericIDictionary(Type type) => type.GetGenericTypeDefinition() == typeof(IDictionary<,>);
|
||||
|
||||
static void ArrayGetElementType(Type arrayType, out Type elementType)
|
||||
{
|
||||
elementType = arrayType.GetGenericArguments()[0];
|
||||
}
|
||||
|
||||
static void DictionaryGetKeyValueTypes(Type dictionaryType, out Type keyType, out Type valueType)
|
||||
{
|
||||
var genericArgs = dictionaryType.GetGenericArguments();
|
||||
keyType = genericArgs[0];
|
||||
valueType = genericArgs[1];
|
||||
}
|
||||
|
||||
static Type MakeGenericArrayType(Type elemType)
|
||||
{
|
||||
return typeof(Godot.Collections.Array<>).MakeGenericType(elemType);
|
||||
}
|
||||
|
||||
static Type MakeGenericDictionaryType(Type keyType, Type valueType)
|
||||
{
|
||||
return typeof(Godot.Collections.Dictionary<,>).MakeGenericType(keyType, valueType);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,428 @@
|
|||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
#if REAL_T_IS_DOUBLE
|
||||
using real_t = System.Double;
|
||||
#else
|
||||
using real_t = System.Single;
|
||||
|
||||
#endif
|
||||
|
||||
namespace Godot.NativeInterop
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct godot_bool
|
||||
{
|
||||
public byte _value;
|
||||
|
||||
public unsafe godot_bool(bool value) => _value = *(byte*)&value;
|
||||
|
||||
public static unsafe implicit operator bool(godot_bool godotBool) => *(bool*)&godotBool._value;
|
||||
public static implicit operator godot_bool(bool @bool) => new godot_bool(@bool);
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct godot_ref : IDisposable
|
||||
{
|
||||
internal IntPtr _reference;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_reference == IntPtr.Zero)
|
||||
return;
|
||||
NativeFuncs.godotsharp_ref_destroy(ref this);
|
||||
_reference = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
internal enum godot_variant_call_error_error
|
||||
{
|
||||
GODOT_CALL_ERROR_CALL_OK = 0,
|
||||
GODOT_CALL_ERROR_CALL_ERROR_INVALID_METHOD,
|
||||
GODOT_CALL_ERROR_CALL_ERROR_INVALID_ARGUMENT,
|
||||
GODOT_CALL_ERROR_CALL_ERROR_TOO_MANY_ARGUMENTS,
|
||||
GODOT_CALL_ERROR_CALL_ERROR_TOO_FEW_ARGUMENTS,
|
||||
GODOT_CALL_ERROR_CALL_ERROR_INSTANCE_IS_NULL,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct godot_variant_call_error
|
||||
{
|
||||
godot_variant_call_error_error error;
|
||||
int argument;
|
||||
Godot.Variant.Type expected;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct godot_variant : IDisposable
|
||||
{
|
||||
[FieldOffset(0)] public Godot.Variant.Type _type;
|
||||
|
||||
// There's padding here
|
||||
|
||||
[FieldOffset(8)] internal godot_variant_data _data;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal unsafe struct godot_variant_data
|
||||
{
|
||||
[FieldOffset(0)] public godot_bool _bool;
|
||||
[FieldOffset(0)] public long _int;
|
||||
[FieldOffset(0)] public double _float;
|
||||
[FieldOffset(0)] public Transform2D* _transform2d;
|
||||
[FieldOffset(0)] public AABB* _aabb;
|
||||
[FieldOffset(0)] public Basis* _basis;
|
||||
[FieldOffset(0)] public Transform3D* _transform3d;
|
||||
[FieldOffset(0)] private godot_variant_data_mem _mem;
|
||||
|
||||
// The following fields are not in the C++ union, but this is how they're stored in _mem.
|
||||
[FieldOffset(0)] public godot_string_name _m_string_name;
|
||||
[FieldOffset(0)] public godot_string _m_string;
|
||||
[FieldOffset(0)] public Vector3 _m_vector3;
|
||||
[FieldOffset(0)] public Vector3i _m_vector3i;
|
||||
[FieldOffset(0)] public Vector2 _m_vector2;
|
||||
[FieldOffset(0)] public Vector2i _m_vector2i;
|
||||
[FieldOffset(0)] public Rect2 _m_rect2;
|
||||
[FieldOffset(0)] public Rect2i _m_rect2i;
|
||||
[FieldOffset(0)] public Plane _m_plane;
|
||||
[FieldOffset(0)] public Quaternion _m_quaternion;
|
||||
[FieldOffset(0)] public Color _m_color;
|
||||
[FieldOffset(0)] public godot_node_path _m_node_path;
|
||||
[FieldOffset(0)] public RID _m_rid;
|
||||
[FieldOffset(0)] public godot_variant_obj_data _m_obj_data;
|
||||
[FieldOffset(0)] public godot_callable _m_callable;
|
||||
[FieldOffset(0)] public godot_signal _m_signal;
|
||||
[FieldOffset(0)] public godot_dictionary _m_dictionary;
|
||||
[FieldOffset(0)] public godot_array _m_array;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct godot_variant_obj_data
|
||||
{
|
||||
public UInt64 id;
|
||||
public IntPtr obj;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
private struct godot_variant_data_mem
|
||||
{
|
||||
#pragma warning disable 169
|
||||
private real_t _mem0;
|
||||
private real_t _mem1;
|
||||
private real_t _mem2;
|
||||
private real_t _mem3;
|
||||
#pragma warning restore 169
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
switch (_type)
|
||||
{
|
||||
case Variant.Type.Nil:
|
||||
case Variant.Type.Bool:
|
||||
case Variant.Type.Int:
|
||||
case Variant.Type.Float:
|
||||
case Variant.Type.Vector2:
|
||||
case Variant.Type.Vector2i:
|
||||
case Variant.Type.Rect2:
|
||||
case Variant.Type.Rect2i:
|
||||
case Variant.Type.Vector3:
|
||||
case Variant.Type.Vector3i:
|
||||
case Variant.Type.Plane:
|
||||
case Variant.Type.Quaternion:
|
||||
case Variant.Type.Color:
|
||||
case Variant.Type.Rid:
|
||||
return;
|
||||
}
|
||||
|
||||
NativeFuncs.godotsharp_variant_destroy(ref this);
|
||||
_type = Variant.Type.Nil;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct godot_string : IDisposable
|
||||
{
|
||||
internal IntPtr _ptr;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_ptr == IntPtr.Zero)
|
||||
return;
|
||||
NativeFuncs.godotsharp_string_destroy(ref this);
|
||||
_ptr = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct godot_string_name : IDisposable
|
||||
{
|
||||
internal IntPtr _data;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_data == IntPtr.Zero)
|
||||
return;
|
||||
NativeFuncs.godotsharp_string_name_destroy(ref this);
|
||||
_data = IntPtr.Zero;
|
||||
}
|
||||
|
||||
// An static method because an instance method could result in a hidden copy if called on an `in` parameter.
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsEmpty(in godot_string_name name) =>
|
||||
// This is all that's needed to check if it's empty. Equivalent to `== StringName()` in C++.
|
||||
name._data == IntPtr.Zero;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct godot_node_path : IDisposable
|
||||
{
|
||||
internal IntPtr _data;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_data == IntPtr.Zero)
|
||||
return;
|
||||
NativeFuncs.godotsharp_node_path_destroy(ref this);
|
||||
_data = IntPtr.Zero;
|
||||
}
|
||||
|
||||
// An static method because an instance method could result in a hidden copy if called on an `in` parameter.
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsEmpty(in godot_node_path nodePath) =>
|
||||
// This is all that's needed to check if it's empty. It's what the `is_empty()` C++ method does.
|
||||
nodePath._data == IntPtr.Zero;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct godot_signal : IDisposable
|
||||
{
|
||||
[FieldOffset(0)] public godot_string_name _name;
|
||||
|
||||
// There's padding here on 32-bit
|
||||
|
||||
[FieldOffset(8)] public UInt64 _objectId;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_name._data == IntPtr.Zero)
|
||||
return;
|
||||
NativeFuncs.godotsharp_signal_destroy(ref this);
|
||||
_name._data = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct godot_callable : IDisposable
|
||||
{
|
||||
[FieldOffset(0)] public godot_string_name _method;
|
||||
|
||||
// There's padding here on 32-bit
|
||||
|
||||
[FieldOffset(8)] public UInt64 _objectId;
|
||||
[FieldOffset(8)] public IntPtr _custom;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_method._data == IntPtr.Zero && _custom == IntPtr.Zero)
|
||||
return;
|
||||
NativeFuncs.godotsharp_callable_destroy(ref this);
|
||||
_method._data = IntPtr.Zero;
|
||||
_custom = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
// A correctly constructed value needs to call the native default constructor to allocate `_p`.
|
||||
// Don't pass a C# default constructed `godot_array` to native code, unless it's going to
|
||||
// be re-assigned a new value (the copy constructor checks if `_p` is null so that's fine).
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct godot_array : IDisposable
|
||||
{
|
||||
internal IntPtr _p;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_p == IntPtr.Zero)
|
||||
return;
|
||||
NativeFuncs.godotsharp_array_destroy(ref this);
|
||||
_p = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
// IMPORTANT:
|
||||
// A correctly constructed value needs to call the native default constructor to allocate `_p`.
|
||||
// Don't pass a C# default constructed `godot_dictionary` to native code, unless it's going to
|
||||
// be re-assigned a new value (the copy constructor checks if `_p` is null so that's fine).
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct godot_dictionary : IDisposable
|
||||
{
|
||||
internal IntPtr _p;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_p == IntPtr.Zero)
|
||||
return;
|
||||
NativeFuncs.godotsharp_dictionary_destroy(ref this);
|
||||
_p = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct godot_packed_byte_array : IDisposable
|
||||
{
|
||||
internal IntPtr _writeProxy;
|
||||
internal IntPtr _ptr;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_ptr == IntPtr.Zero)
|
||||
return;
|
||||
NativeFuncs.godotsharp_packed_byte_array_destroy(ref this);
|
||||
_ptr = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct godot_packed_int32_array : IDisposable
|
||||
{
|
||||
internal IntPtr _writeProxy;
|
||||
internal IntPtr _ptr;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_ptr == IntPtr.Zero)
|
||||
return;
|
||||
NativeFuncs.godotsharp_packed_int32_array_destroy(ref this);
|
||||
_ptr = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct godot_packed_int64_array : IDisposable
|
||||
{
|
||||
internal IntPtr _writeProxy;
|
||||
internal IntPtr _ptr;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_ptr == IntPtr.Zero)
|
||||
return;
|
||||
NativeFuncs.godotsharp_packed_int64_array_destroy(ref this);
|
||||
_ptr = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct godot_packed_float32_array : IDisposable
|
||||
{
|
||||
internal IntPtr _writeProxy;
|
||||
internal IntPtr _ptr;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_ptr == IntPtr.Zero)
|
||||
return;
|
||||
NativeFuncs.godotsharp_packed_float32_array_destroy(ref this);
|
||||
_ptr = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct godot_packed_float64_array : IDisposable
|
||||
{
|
||||
internal IntPtr _writeProxy;
|
||||
internal IntPtr _ptr;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_ptr == IntPtr.Zero)
|
||||
return;
|
||||
NativeFuncs.godotsharp_packed_float64_array_destroy(ref this);
|
||||
_ptr = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct godot_packed_string_array : IDisposable
|
||||
{
|
||||
internal IntPtr _writeProxy;
|
||||
internal IntPtr _ptr;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_ptr == IntPtr.Zero)
|
||||
return;
|
||||
NativeFuncs.godotsharp_packed_string_array_destroy(ref this);
|
||||
_ptr = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct godot_packed_vector2_array : IDisposable
|
||||
{
|
||||
internal IntPtr _writeProxy;
|
||||
internal IntPtr _ptr;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_ptr == IntPtr.Zero)
|
||||
return;
|
||||
NativeFuncs.godotsharp_packed_vector2_array_destroy(ref this);
|
||||
_ptr = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct godot_packed_vector3_array : IDisposable
|
||||
{
|
||||
internal IntPtr _writeProxy;
|
||||
internal IntPtr _ptr;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_ptr == IntPtr.Zero)
|
||||
return;
|
||||
NativeFuncs.godotsharp_packed_vector3_array_destroy(ref this);
|
||||
_ptr = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal struct godot_packed_color_array : IDisposable
|
||||
{
|
||||
internal IntPtr _writeProxy;
|
||||
internal IntPtr _ptr;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_ptr == IntPtr.Zero)
|
||||
return;
|
||||
NativeFuncs.godotsharp_packed_color_array_destroy(ref this);
|
||||
_ptr = IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Godot.NativeInterop
|
||||
{
|
||||
internal static class InteropUtils
|
||||
{
|
||||
public static Object UnmanagedGetManaged(IntPtr unmanaged)
|
||||
{
|
||||
// TODO: Move to C#
|
||||
return internal_unmanaged_get_managed(unmanaged);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern Object internal_unmanaged_get_managed(IntPtr unmanaged);
|
||||
|
||||
public static void TieManagedToUnmanaged(Object managed, IntPtr unmanaged)
|
||||
{
|
||||
// TODO: Move to C#
|
||||
internal_tie_managed_to_unmanaged(managed, unmanaged);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern void internal_tie_managed_to_unmanaged(Object managed, IntPtr unmanaged);
|
||||
|
||||
public static unsafe Object EngineGetSingleton(string name)
|
||||
{
|
||||
using godot_string src = Marshaling.mono_string_to_godot(name);
|
||||
return UnmanagedGetManaged(NativeFuncs.godotsharp_engine_get_singleton(&src));
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,328 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace Godot.NativeInterop
|
||||
{
|
||||
#if !NET
|
||||
// This improves P/Invoke performance.
|
||||
// The attribute is not available with .NET Core and it's not needed there.
|
||||
[System.Security.SuppressUnmanagedCodeSecurity]
|
||||
#endif
|
||||
internal static unsafe partial class NativeFuncs
|
||||
{
|
||||
private const string GodotDllName = "__Internal";
|
||||
|
||||
// Custom functions
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern IntPtr godotsharp_method_bind_get_method(ref godot_string_name p_classname, char* p_methodname);
|
||||
|
||||
#if NET
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern delegate* unmanaged<IntPtr> godotsharp_get_class_constructor(ref godot_string_name p_classname);
|
||||
#else
|
||||
// Workaround until we switch to .NET 5/6
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern IntPtr godotsharp_get_class_constructor(ref godot_string_name p_classname);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern IntPtr godotsharp_invoke_class_constructor(IntPtr p_creation_func);
|
||||
#endif
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern IntPtr godotsharp_engine_get_singleton(godot_string* p_name);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_ref_destroy(ref godot_ref p_instance);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_string_name_new_from_string(godot_string_name* dest, godot_string* name);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_node_path_new_from_string(godot_node_path* dest, godot_string* name);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_string_name_as_string(godot_string* r_dest, godot_string_name* p_name);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_node_path_as_string(godot_string* r_dest, godot_node_path* p_np);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_packed_byte_array godotsharp_packed_byte_array_new_mem_copy(byte* p_src, int p_length);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_packed_int32_array godotsharp_packed_int32_array_new_mem_copy(int* p_src, int p_length);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_packed_int64_array godotsharp_packed_int64_array_new_mem_copy(long* p_src, int p_length);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_packed_float32_array godotsharp_packed_float32_array_new_mem_copy(float* p_src, int p_length);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_packed_float64_array godotsharp_packed_float64_array_new_mem_copy(double* p_src, int p_length);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_packed_vector2_array godotsharp_packed_vector2_array_new_mem_copy(Vector2* p_src, int p_length);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_packed_vector3_array godotsharp_packed_vector3_array_new_mem_copy(Vector3* p_src, int p_length);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_packed_color_array godotsharp_packed_color_array_new_mem_copy(Color* p_src, int p_length);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_packed_string_array_add(godot_packed_string_array* r_dest, godot_string* p_element);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_callable_new_with_delegate(IntPtr p_delegate_handle, godot_callable* r_callable);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern bool godotsharp_callable_get_data_for_marshalling(godot_callable* p_callable, IntPtr* r_delegate_handle, IntPtr* r_object, godot_string_name* r_name);
|
||||
|
||||
// GDNative functions
|
||||
|
||||
// gdnative.h
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_method_bind_ptrcall(IntPtr p_method_bind, IntPtr p_instance, void** p_args, void* p_ret);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_variant godotsharp_method_bind_call(IntPtr p_method_bind, IntPtr p_instance, godot_variant** p_args, int p_arg_count, godot_variant_call_error* p_call_error);
|
||||
|
||||
// variant.h
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_variant_new_string_name(godot_variant* r_dest, godot_string_name* p_s);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_variant_new_node_path(godot_variant* r_dest, godot_node_path* p_np);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_variant_new_object(godot_variant* r_dest, IntPtr p_obj);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_variant_new_transform2d(godot_variant* r_dest, Transform2D* p_t2d);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_variant_new_basis(godot_variant* r_dest, Basis* p_basis);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_variant_new_transform3d(godot_variant* r_dest, Transform3D* p_trans);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_variant_new_aabb(godot_variant* r_dest, AABB* p_aabb);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_variant_new_dictionary(godot_variant* r_dest, godot_dictionary* p_dict);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_variant_new_array(godot_variant* r_dest, godot_array* p_arr);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_variant_new_packed_byte_array(godot_variant* r_dest, godot_packed_byte_array* p_pba);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_variant_new_packed_int32_array(godot_variant* r_dest, godot_packed_int32_array* p_pia);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_variant_new_packed_int64_array(godot_variant* r_dest, godot_packed_int64_array* p_pia);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_variant_new_packed_float32_array(godot_variant* r_dest, godot_packed_float32_array* p_pra);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_variant_new_packed_float64_array(godot_variant* r_dest, godot_packed_float64_array* p_pra);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_variant_new_packed_string_array(godot_variant* r_dest, godot_packed_string_array* p_psa);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_variant_new_packed_vector2_array(godot_variant* r_dest, godot_packed_vector2_array* p_pv2a);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_variant_new_packed_vector3_array(godot_variant* r_dest, godot_packed_vector3_array* p_pv3a);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_variant_new_packed_color_array(godot_variant* r_dest, godot_packed_color_array* p_pca);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern bool godotsharp_variant_as_bool(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern Int64 godotsharp_variant_as_int(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern double godotsharp_variant_as_float(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_string godotsharp_variant_as_string(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern Vector2 godotsharp_variant_as_vector2(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern Vector2i godotsharp_variant_as_vector2i(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern Rect2 godotsharp_variant_as_rect2(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern Rect2i godotsharp_variant_as_rect2i(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern Vector3 godotsharp_variant_as_vector3(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern Vector3i godotsharp_variant_as_vector3i(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern Transform2D godotsharp_variant_as_transform2d(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern Plane godotsharp_variant_as_plane(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern Quaternion godotsharp_variant_as_quaternion(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern AABB godotsharp_variant_as_aabb(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern Basis godotsharp_variant_as_basis(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern Transform3D godotsharp_variant_as_transform3d(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern Color godotsharp_variant_as_color(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_string_name godotsharp_variant_as_string_name(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_node_path godotsharp_variant_as_node_path(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern RID godotsharp_variant_as_rid(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_callable godotsharp_variant_as_callable(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_signal godotsharp_variant_as_signal(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_dictionary godotsharp_variant_as_dictionary(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_array godotsharp_variant_as_array(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_packed_byte_array godotsharp_variant_as_packed_byte_array(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_packed_int32_array godotsharp_variant_as_packed_int32_array(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_packed_int64_array godotsharp_variant_as_packed_int64_array(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_packed_float32_array godotsharp_variant_as_packed_float32_array(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_packed_float64_array godotsharp_variant_as_packed_float64_array(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_packed_string_array godotsharp_variant_as_packed_string_array(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_packed_vector2_array godotsharp_variant_as_packed_vector2_array(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_packed_vector3_array godotsharp_variant_as_packed_vector3_array(godot_variant* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_packed_color_array godotsharp_variant_as_packed_color_array(godot_variant* p_self);
|
||||
|
||||
// string.h
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_string_new_with_utf16_chars(godot_string* r_dest, char* p_contents);
|
||||
|
||||
// string_name.h
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_string_name_new_copy(godot_string_name* r_dest, godot_string_name* p_src);
|
||||
|
||||
// node_path.h
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_node_path_new_copy(godot_node_path* r_dest, godot_node_path* p_src);
|
||||
|
||||
// array.h
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_array_new_copy(godot_array* r_dest, godot_array* p_src);
|
||||
|
||||
// dictionary.h
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_dictionary_new_copy(godot_dictionary* r_dest, godot_dictionary* p_src);
|
||||
|
||||
// destroy functions
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_packed_byte_array_destroy(ref godot_packed_byte_array p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_packed_int32_array_destroy(ref godot_packed_int32_array p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_packed_int64_array_destroy(ref godot_packed_int64_array p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_packed_float32_array_destroy(ref godot_packed_float32_array p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_packed_float64_array_destroy(ref godot_packed_float64_array p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_packed_string_array_destroy(ref godot_packed_string_array p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_packed_vector2_array_destroy(ref godot_packed_vector2_array p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_packed_vector3_array_destroy(ref godot_packed_vector3_array p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_packed_color_array_destroy(ref godot_packed_color_array p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_variant_destroy(ref godot_variant p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_string_destroy(ref godot_string p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_string_name_destroy(ref godot_string_name p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_node_path_destroy(ref godot_node_path p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_signal_destroy(ref godot_signal p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_callable_destroy(ref godot_callable p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_array_destroy(ref godot_array p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_dictionary_destroy(ref godot_dictionary p_self);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace Godot.NativeInterop
|
||||
{
|
||||
internal static unsafe partial class NativeFuncs
|
||||
{
|
||||
public static godot_string_name godotsharp_string_name_new_copy(godot_string_name* src)
|
||||
{
|
||||
godot_string_name ret;
|
||||
godotsharp_string_name_new_copy(&ret, src);
|
||||
return ret;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static godot_string_name godotsharp_string_name_new_copy(godot_string_name src)
|
||||
=> godotsharp_string_name_new_copy(&src);
|
||||
|
||||
public static godot_node_path godotsharp_node_path_new_copy(godot_node_path* src)
|
||||
{
|
||||
godot_node_path ret;
|
||||
godotsharp_node_path_new_copy(&ret, src);
|
||||
return ret;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static godot_node_path godotsharp_node_path_new_copy(godot_node_path src)
|
||||
=> godotsharp_node_path_new_copy(&src);
|
||||
|
||||
public static godot_array godotsharp_array_new_copy(godot_array* src)
|
||||
{
|
||||
godot_array ret;
|
||||
godotsharp_array_new_copy(&ret, src);
|
||||
return ret;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static godot_array godotsharp_array_new_copy(godot_array src)
|
||||
=> godotsharp_array_new_copy(&src);
|
||||
|
||||
public static godot_dictionary godotsharp_dictionary_new_copy(godot_dictionary* src)
|
||||
{
|
||||
godot_dictionary ret;
|
||||
godotsharp_dictionary_new_copy(&ret, src);
|
||||
return ret;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static godot_dictionary godotsharp_dictionary_new_copy(godot_dictionary src)
|
||||
=> godotsharp_dictionary_new_copy(&src);
|
||||
|
||||
public static godot_string_name godotsharp_string_name_new_from_string(string name)
|
||||
{
|
||||
godot_string_name ret;
|
||||
using godot_string src = Marshaling.mono_string_to_godot(name);
|
||||
godotsharp_string_name_new_from_string(&ret, &src);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static godot_node_path godotsharp_node_path_new_from_string(string name)
|
||||
{
|
||||
godot_node_path ret;
|
||||
using godot_string src = Marshaling.mono_string_to_godot(name);
|
||||
godotsharp_node_path_new_from_string(&ret, &src);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
using System;
|
||||
|
||||
namespace Godot.NativeInterop
|
||||
{
|
||||
internal ref struct VariantSpanDisposer
|
||||
{
|
||||
private readonly Span<godot_variant> _variantSpan;
|
||||
|
||||
// IMPORTANT: The span element must be default initialized.
|
||||
// Make sure call Clear() on the span if it was created with stackalloc.
|
||||
public VariantSpanDisposer(Span<godot_variant> variantSpan)
|
||||
{
|
||||
_variantSpan = variantSpan;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
for (int i = 0; i < _variantSpan.Length; i++)
|
||||
_variantSpan[i].Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
internal static class VariantSpanExtensions
|
||||
{
|
||||
// Used to make sure we always initialize the span values to the default,
|
||||
// as we need that in order to safely dispose all elements after.
|
||||
public static Span<godot_variant> Cleared(this Span<godot_variant> span)
|
||||
{
|
||||
span.Clear();
|
||||
return span;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,305 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace Godot.NativeInterop
|
||||
{
|
||||
internal static class VariantUtils
|
||||
{
|
||||
public static godot_variant CreateFromRID(RID from)
|
||||
=> new() {_type = Variant.Type.Rid, _data = {_m_rid = from}};
|
||||
|
||||
public static godot_variant CreateFromBool(bool from)
|
||||
=> new() {_type = Variant.Type.Bool, _data = {_bool = from}};
|
||||
|
||||
public static godot_variant CreateFromInt(long from)
|
||||
=> new() {_type = Variant.Type.Int, _data = {_int = from}};
|
||||
|
||||
public static godot_variant CreateFromInt(ulong from)
|
||||
=> new() {_type = Variant.Type.Int, _data = {_int = (long)from}};
|
||||
|
||||
public static godot_variant CreateFromFloat(double from)
|
||||
=> new() {_type = Variant.Type.Float, _data = {_float = from}};
|
||||
|
||||
public static godot_variant CreateFromVector2(Vector2 from)
|
||||
=> new() {_type = Variant.Type.Vector2, _data = {_m_vector2 = from}};
|
||||
|
||||
public static godot_variant CreateFromVector2i(Vector2i from)
|
||||
=> new() {_type = Variant.Type.Vector2i, _data = {_m_vector2i = from}};
|
||||
|
||||
public static godot_variant CreateFromVector3(Vector3 from)
|
||||
=> new() {_type = Variant.Type.Vector3, _data = {_m_vector3 = from}};
|
||||
|
||||
public static godot_variant CreateFromVector3i(Vector3i from)
|
||||
=> new() {_type = Variant.Type.Vector3i, _data = {_m_vector3i = from}};
|
||||
|
||||
public static godot_variant CreateFromRect2(Rect2 from)
|
||||
=> new() {_type = Variant.Type.Rect2, _data = {_m_rect2 = from}};
|
||||
|
||||
public static godot_variant CreateFromRect2i(Rect2i from)
|
||||
=> new() {_type = Variant.Type.Rect2i, _data = {_m_rect2i = from}};
|
||||
|
||||
public static godot_variant CreateFromQuaternion(Quaternion from)
|
||||
=> new() {_type = Variant.Type.Quaternion, _data = {_m_quaternion = from}};
|
||||
|
||||
public static godot_variant CreateFromColor(Color from)
|
||||
=> new() {_type = Variant.Type.Color, _data = {_m_color = from}};
|
||||
|
||||
public static godot_variant CreateFromPlane(Plane from)
|
||||
=> new() {_type = Variant.Type.Plane, _data = {_m_plane = from}};
|
||||
|
||||
public static unsafe godot_variant CreateFromTransform2D(Transform2D from)
|
||||
{
|
||||
godot_variant ret;
|
||||
NativeFuncs.godotsharp_variant_new_transform2d(&ret, &from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static unsafe godot_variant CreateFromBasis(Basis from)
|
||||
{
|
||||
godot_variant ret;
|
||||
NativeFuncs.godotsharp_variant_new_basis(&ret, &from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static unsafe godot_variant CreateFromTransform3D(Transform3D from)
|
||||
{
|
||||
godot_variant ret;
|
||||
NativeFuncs.godotsharp_variant_new_transform3d(&ret, &from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static unsafe godot_variant CreateFromAABB(AABB from)
|
||||
{
|
||||
godot_variant ret;
|
||||
NativeFuncs.godotsharp_variant_new_aabb(&ret, &from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Explicit name to make it very clear
|
||||
public static godot_variant CreateFromCallableTakingOwnershipOfDisposableValue(godot_callable from)
|
||||
=> new() {_type = Variant.Type.Callable, _data = {_m_callable = from}};
|
||||
|
||||
// Explicit name to make it very clear
|
||||
public static godot_variant CreateFromSignalTakingOwnershipOfDisposableValue(godot_signal from)
|
||||
=> new() {_type = Variant.Type.Signal, _data = {_m_signal = from}};
|
||||
|
||||
// Explicit name to make it very clear
|
||||
public static godot_variant CreateFromStringTakingOwnershipOfDisposableValue(godot_string from)
|
||||
=> new() {_type = Variant.Type.String, _data = {_m_string = from}};
|
||||
|
||||
public static unsafe godot_variant CreateFromPackedByteArray(godot_packed_byte_array* from)
|
||||
{
|
||||
godot_variant ret;
|
||||
NativeFuncs.godotsharp_variant_new_packed_byte_array(&ret, from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static unsafe godot_variant CreateFromPackedInt32Array(godot_packed_int32_array* from)
|
||||
{
|
||||
godot_variant ret;
|
||||
NativeFuncs.godotsharp_variant_new_packed_int32_array(&ret, from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static unsafe godot_variant CreateFromPackedInt64Array(godot_packed_int64_array* from)
|
||||
{
|
||||
godot_variant ret;
|
||||
NativeFuncs.godotsharp_variant_new_packed_int64_array(&ret, from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static unsafe godot_variant CreateFromPackedFloat32Array(godot_packed_float32_array* from)
|
||||
{
|
||||
godot_variant ret;
|
||||
NativeFuncs.godotsharp_variant_new_packed_float32_array(&ret, from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static unsafe godot_variant CreateFromPackedFloat64Array(godot_packed_float64_array* from)
|
||||
{
|
||||
godot_variant ret;
|
||||
NativeFuncs.godotsharp_variant_new_packed_float64_array(&ret, from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static unsafe godot_variant CreateFromPackedStringArray(godot_packed_string_array* from)
|
||||
{
|
||||
godot_variant ret;
|
||||
NativeFuncs.godotsharp_variant_new_packed_string_array(&ret, from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static unsafe godot_variant CreateFromPackedVector2Array(godot_packed_vector2_array* from)
|
||||
{
|
||||
godot_variant ret;
|
||||
NativeFuncs.godotsharp_variant_new_packed_vector2_array(&ret, from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static unsafe godot_variant CreateFromPackedVector3Array(godot_packed_vector3_array* from)
|
||||
{
|
||||
godot_variant ret;
|
||||
NativeFuncs.godotsharp_variant_new_packed_vector3_array(&ret, from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static unsafe godot_variant CreateFromPackedColorArray(godot_packed_color_array* from)
|
||||
{
|
||||
godot_variant ret;
|
||||
NativeFuncs.godotsharp_variant_new_packed_color_array(&ret, from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static unsafe godot_variant CreateFromArray(godot_array* from)
|
||||
{
|
||||
godot_variant ret;
|
||||
NativeFuncs.godotsharp_variant_new_array(&ret, from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static unsafe godot_variant CreateFromArray(godot_array from)
|
||||
=> CreateFromArray(&from);
|
||||
|
||||
public static unsafe godot_variant CreateFromDictionary(godot_dictionary* from)
|
||||
{
|
||||
godot_variant ret;
|
||||
NativeFuncs.godotsharp_variant_new_dictionary(&ret, from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static unsafe godot_variant CreateFromDictionary(godot_dictionary from)
|
||||
=> CreateFromDictionary(&from);
|
||||
|
||||
public static unsafe godot_variant CreateFromStringName(ref godot_string_name arg1)
|
||||
{
|
||||
godot_variant ret;
|
||||
godot_string_name src = arg1;
|
||||
NativeFuncs.godotsharp_variant_new_string_name(&ret, &src);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static unsafe godot_variant CreateFromNodePath(ref godot_node_path arg1)
|
||||
{
|
||||
godot_variant ret;
|
||||
godot_node_path src = arg1;
|
||||
NativeFuncs.godotsharp_variant_new_node_path(&ret, &src);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static unsafe godot_variant CreateFromGodotObject(IntPtr from)
|
||||
{
|
||||
if (from == IntPtr.Zero)
|
||||
return new godot_variant();
|
||||
godot_variant ret;
|
||||
NativeFuncs.godotsharp_variant_new_object(&ret, from);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// We avoid the internal call if the stored type is the same we want.
|
||||
|
||||
public static unsafe bool ConvertToBool(godot_variant* p_var)
|
||||
=> (*p_var)._type == Variant.Type.Bool ? (*p_var)._data._bool : NativeFuncs.godotsharp_variant_as_bool(p_var);
|
||||
|
||||
public static unsafe char ConvertToChar(godot_variant* p_var)
|
||||
=> (char)((*p_var)._type == Variant.Type.Int ? (*p_var)._data._int : NativeFuncs.godotsharp_variant_as_int(p_var));
|
||||
|
||||
public static unsafe sbyte ConvertToInt8(godot_variant* p_var)
|
||||
=> (sbyte)((*p_var)._type == Variant.Type.Int ? (*p_var)._data._int : NativeFuncs.godotsharp_variant_as_int(p_var));
|
||||
|
||||
public static unsafe Int16 ConvertToInt16(godot_variant* p_var)
|
||||
=> (Int16)((*p_var)._type == Variant.Type.Int ? (*p_var)._data._int : NativeFuncs.godotsharp_variant_as_int(p_var));
|
||||
|
||||
public static unsafe Int32 ConvertToInt32(godot_variant* p_var)
|
||||
=> (Int32)((*p_var)._type == Variant.Type.Int ? (*p_var)._data._int : NativeFuncs.godotsharp_variant_as_int(p_var));
|
||||
|
||||
public static unsafe Int64 ConvertToInt64(godot_variant* p_var)
|
||||
=> (*p_var)._type == Variant.Type.Int ? (*p_var)._data._int : NativeFuncs.godotsharp_variant_as_int(p_var);
|
||||
|
||||
public static unsafe byte ConvertToUInt8(godot_variant* p_var)
|
||||
=> (byte)((*p_var)._type == Variant.Type.Int ? (*p_var)._data._int : NativeFuncs.godotsharp_variant_as_int(p_var));
|
||||
|
||||
public static unsafe UInt16 ConvertToUInt16(godot_variant* p_var)
|
||||
=> (UInt16)((*p_var)._type == Variant.Type.Int ? (*p_var)._data._int : NativeFuncs.godotsharp_variant_as_int(p_var));
|
||||
|
||||
public static unsafe UInt32 ConvertToUInt32(godot_variant* p_var)
|
||||
=> (UInt32)((*p_var)._type == Variant.Type.Int ? (*p_var)._data._int : NativeFuncs.godotsharp_variant_as_int(p_var));
|
||||
|
||||
public static unsafe UInt64 ConvertToUInt64(godot_variant* p_var)
|
||||
=> (UInt64)((*p_var)._type == Variant.Type.Int ? (*p_var)._data._int : NativeFuncs.godotsharp_variant_as_int(p_var));
|
||||
|
||||
public static unsafe float ConvertToFloat32(godot_variant* p_var)
|
||||
=> (float)((*p_var)._type == Variant.Type.Float ? (*p_var)._data._float : NativeFuncs.godotsharp_variant_as_float(p_var));
|
||||
|
||||
public static unsafe double ConvertToFloat64(godot_variant* p_var)
|
||||
=> (*p_var)._type == Variant.Type.Float ? (*p_var)._data._float : NativeFuncs.godotsharp_variant_as_float(p_var);
|
||||
|
||||
public static unsafe Vector2 ConvertToVector2(godot_variant* p_var)
|
||||
=> (*p_var)._type == Variant.Type.Vector2 ? (*p_var)._data._m_vector2 : NativeFuncs.godotsharp_variant_as_vector2(p_var);
|
||||
|
||||
public static unsafe Vector2i ConvertToVector2i(godot_variant* p_var)
|
||||
=> (*p_var)._type == Variant.Type.Vector2i ? (*p_var)._data._m_vector2i : NativeFuncs.godotsharp_variant_as_vector2i(p_var);
|
||||
|
||||
public static unsafe Rect2 ConvertToRect2(godot_variant* p_var)
|
||||
=> (*p_var)._type == Variant.Type.Rect2 ? (*p_var)._data._m_rect2 : NativeFuncs.godotsharp_variant_as_rect2(p_var);
|
||||
|
||||
public static unsafe Rect2i ConvertToRect2i(godot_variant* p_var)
|
||||
=> (*p_var)._type == Variant.Type.Rect2i ? (*p_var)._data._m_rect2i : NativeFuncs.godotsharp_variant_as_rect2i(p_var);
|
||||
|
||||
public static unsafe Transform2D ConvertToTransform2D(godot_variant* p_var)
|
||||
=> (*p_var)._type == Variant.Type.Transform2d ? *(*p_var)._data._transform2d : NativeFuncs.godotsharp_variant_as_transform2d(p_var);
|
||||
|
||||
public static unsafe Vector3 ConvertToVector3(godot_variant* p_var)
|
||||
=> (*p_var)._type == Variant.Type.Vector3 ? (*p_var)._data._m_vector3 : NativeFuncs.godotsharp_variant_as_vector3(p_var);
|
||||
|
||||
public static unsafe Vector3i ConvertToVector3i(godot_variant* p_var)
|
||||
=> (*p_var)._type == Variant.Type.Vector3i ? (*p_var)._data._m_vector3i : NativeFuncs.godotsharp_variant_as_vector3i(p_var);
|
||||
|
||||
public static unsafe Basis ConvertToBasis(godot_variant* p_var)
|
||||
=> (*p_var)._type == Variant.Type.Basis ? *(*p_var)._data._basis : NativeFuncs.godotsharp_variant_as_basis(p_var);
|
||||
|
||||
public static unsafe Quaternion ConvertToQuaternion(godot_variant* p_var)
|
||||
=> (*p_var)._type == Variant.Type.Quaternion ? (*p_var)._data._m_quaternion : NativeFuncs.godotsharp_variant_as_quaternion(p_var);
|
||||
|
||||
public static unsafe Transform3D ConvertToTransform3D(godot_variant* p_var)
|
||||
=> (*p_var)._type == Variant.Type.Transform3d ? *(*p_var)._data._transform3d : NativeFuncs.godotsharp_variant_as_transform3d(p_var);
|
||||
|
||||
public static unsafe AABB ConvertToAABB(godot_variant* p_var)
|
||||
=> (*p_var)._type == Variant.Type.Aabb ? *(*p_var)._data._aabb : NativeFuncs.godotsharp_variant_as_aabb(p_var);
|
||||
|
||||
public static unsafe Color ConvertToColor(godot_variant* p_var)
|
||||
=> (*p_var)._type == Variant.Type.Color ? (*p_var)._data._m_color : NativeFuncs.godotsharp_variant_as_color(p_var);
|
||||
|
||||
public static unsafe Plane ConvertToPlane(godot_variant* p_var)
|
||||
=> (*p_var)._type == Variant.Type.Plane ? (*p_var)._data._m_plane : NativeFuncs.godotsharp_variant_as_plane(p_var);
|
||||
|
||||
public static unsafe IntPtr ConvertToGodotObject(godot_variant* p_var)
|
||||
=> (*p_var)._type == Variant.Type.Object ? (*p_var)._data._m_obj_data.obj : IntPtr.Zero;
|
||||
|
||||
public static unsafe RID ConvertToRID(godot_variant* p_var)
|
||||
=> (*p_var)._type == Variant.Type.Rid ? (*p_var)._data._m_rid : NativeFuncs.godotsharp_variant_as_rid(p_var);
|
||||
|
||||
public static unsafe godot_string_name ConvertToStringName(godot_variant* p_var)
|
||||
=> (*p_var)._type == Variant.Type.StringName ?
|
||||
NativeFuncs.godotsharp_string_name_new_copy(&(*p_var)._data._m_string_name) :
|
||||
NativeFuncs.godotsharp_variant_as_string_name(p_var);
|
||||
|
||||
public static unsafe godot_node_path ConvertToNodePath(godot_variant* p_var)
|
||||
=> (*p_var)._type == Variant.Type.NodePath ?
|
||||
NativeFuncs.godotsharp_node_path_new_copy(&(*p_var)._data._m_node_path) :
|
||||
NativeFuncs.godotsharp_variant_as_node_path(p_var);
|
||||
|
||||
public static unsafe godot_array ConvertToArray(godot_variant* p_var)
|
||||
=> (*p_var)._type == Variant.Type.Array ?
|
||||
NativeFuncs.godotsharp_array_new_copy(&(*p_var)._data._m_array) :
|
||||
NativeFuncs.godotsharp_variant_as_array(p_var);
|
||||
|
||||
public static unsafe godot_dictionary ConvertToDictionary(godot_variant* p_var)
|
||||
=> (*p_var)._type == Variant.Type.Dictionary ?
|
||||
NativeFuncs.godotsharp_dictionary_new_copy(&(*p_var)._data._m_dictionary) :
|
||||
NativeFuncs.godotsharp_variant_as_dictionary(p_var);
|
||||
}
|
||||
}
|
|
@ -1,24 +1,12 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
namespace Godot
|
||||
{
|
||||
public sealed partial class NodePath : IDisposable
|
||||
public sealed class NodePath : IDisposable
|
||||
{
|
||||
private bool disposed = false;
|
||||
|
||||
private IntPtr ptr;
|
||||
|
||||
internal static IntPtr GetPtr(NodePath instance)
|
||||
{
|
||||
if (instance == null)
|
||||
throw new NullReferenceException($"The instance of type {nameof(NodePath)} is null.");
|
||||
|
||||
if (instance.disposed)
|
||||
throw new ObjectDisposedException(instance.GetType().FullName);
|
||||
|
||||
return instance.ptr;
|
||||
}
|
||||
internal godot_node_path NativeValue;
|
||||
|
||||
~NodePath()
|
||||
{
|
||||
|
@ -31,112 +19,105 @@ namespace Godot
|
|||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
public void Dispose(bool disposing)
|
||||
{
|
||||
if (disposed)
|
||||
return;
|
||||
|
||||
if (ptr != IntPtr.Zero)
|
||||
{
|
||||
godot_icall_NodePath_Dtor(ptr);
|
||||
ptr = IntPtr.Zero;
|
||||
}
|
||||
|
||||
disposed = true;
|
||||
// Always dispose `NativeValue` even if disposing is true
|
||||
NativeValue.Dispose();
|
||||
}
|
||||
|
||||
internal NodePath(IntPtr ptr)
|
||||
private NodePath(godot_node_path nativeValueToOwn)
|
||||
{
|
||||
this.ptr = ptr;
|
||||
NativeValue = nativeValueToOwn;
|
||||
}
|
||||
|
||||
public NodePath() : this(string.Empty) {}
|
||||
// Explicit name to make it very clear
|
||||
internal static NodePath CreateTakingOwnershipOfDisposableValue(godot_node_path nativeValueToOwn)
|
||||
=> new NodePath(nativeValueToOwn);
|
||||
|
||||
public NodePath()
|
||||
{
|
||||
}
|
||||
|
||||
public NodePath(string path)
|
||||
{
|
||||
ptr = godot_icall_NodePath_Ctor(path);
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
NativeValue = NativeFuncs.godotsharp_node_path_new_from_string(path);
|
||||
}
|
||||
|
||||
public static implicit operator NodePath(string from) => new NodePath(from);
|
||||
|
||||
public static implicit operator string(NodePath from) => from.ToString();
|
||||
|
||||
public override string ToString()
|
||||
public override unsafe string ToString()
|
||||
{
|
||||
return godot_icall_NodePath_operator_String(GetPtr(this));
|
||||
if (IsEmpty)
|
||||
return string.Empty;
|
||||
|
||||
godot_string dest;
|
||||
godot_node_path src = NativeValue;
|
||||
NativeFuncs.godotsharp_node_path_as_string(&dest, &src);
|
||||
using (dest)
|
||||
return Marshaling.mono_string_from_godot(&dest);
|
||||
}
|
||||
|
||||
public NodePath GetAsPropertyPath()
|
||||
{
|
||||
return new NodePath(godot_icall_NodePath_get_as_property_path(GetPtr(this)));
|
||||
godot_node_path propertyPath = default;
|
||||
godot_icall_NodePath_get_as_property_path(ref NativeValue, ref propertyPath);
|
||||
return CreateTakingOwnershipOfDisposableValue(propertyPath);
|
||||
}
|
||||
|
||||
public string GetConcatenatedSubnames()
|
||||
public string GetConcatenatedSubNames()
|
||||
{
|
||||
return godot_icall_NodePath_get_concatenated_subnames(GetPtr(this));
|
||||
return godot_icall_NodePath_get_concatenated_subnames(ref NativeValue);
|
||||
}
|
||||
|
||||
public string GetName(int idx)
|
||||
{
|
||||
return godot_icall_NodePath_get_name(GetPtr(this), idx);
|
||||
return godot_icall_NodePath_get_name(ref NativeValue, idx);
|
||||
}
|
||||
|
||||
public int GetNameCount()
|
||||
{
|
||||
return godot_icall_NodePath_get_name_count(GetPtr(this));
|
||||
return godot_icall_NodePath_get_name_count(ref NativeValue);
|
||||
}
|
||||
|
||||
public string GetSubname(int idx)
|
||||
public string GetSubName(int idx)
|
||||
{
|
||||
return godot_icall_NodePath_get_subname(GetPtr(this), idx);
|
||||
return godot_icall_NodePath_get_subname(ref NativeValue, idx);
|
||||
}
|
||||
|
||||
public int GetSubnameCount()
|
||||
public int GetSubNameCount()
|
||||
{
|
||||
return godot_icall_NodePath_get_subname_count(GetPtr(this));
|
||||
return godot_icall_NodePath_get_subname_count(ref NativeValue);
|
||||
}
|
||||
|
||||
public bool IsAbsolute()
|
||||
{
|
||||
return godot_icall_NodePath_is_absolute(GetPtr(this));
|
||||
return godot_icall_NodePath_is_absolute(ref NativeValue);
|
||||
}
|
||||
|
||||
public bool IsEmpty()
|
||||
{
|
||||
return godot_icall_NodePath_is_empty(GetPtr(this));
|
||||
}
|
||||
public bool IsEmpty => godot_node_path.IsEmpty(in NativeValue);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern IntPtr godot_icall_NodePath_Ctor(string path);
|
||||
private static extern void godot_icall_NodePath_get_as_property_path(ref godot_node_path ptr, ref godot_node_path dest);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern void godot_icall_NodePath_Dtor(IntPtr ptr);
|
||||
private static extern string godot_icall_NodePath_get_concatenated_subnames(ref godot_node_path ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string godot_icall_NodePath_operator_String(IntPtr ptr);
|
||||
private static extern string godot_icall_NodePath_get_name(ref godot_node_path ptr, int arg1);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern IntPtr godot_icall_NodePath_get_as_property_path(IntPtr ptr);
|
||||
private static extern int godot_icall_NodePath_get_name_count(ref godot_node_path ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string godot_icall_NodePath_get_concatenated_subnames(IntPtr ptr);
|
||||
private static extern string godot_icall_NodePath_get_subname(ref godot_node_path ptr, int arg1);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string godot_icall_NodePath_get_name(IntPtr ptr, int arg1);
|
||||
private static extern int godot_icall_NodePath_get_subname_count(ref godot_node_path ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern int godot_icall_NodePath_get_name_count(IntPtr ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string godot_icall_NodePath_get_subname(IntPtr ptr, int arg1);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern int godot_icall_NodePath_get_subname_count(IntPtr ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern bool godot_icall_NodePath_is_absolute(IntPtr ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern bool godot_icall_NodePath_is_empty(IntPtr ptr);
|
||||
private static extern bool godot_icall_NodePath_is_absolute(ref godot_node_path ptr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,44 +5,50 @@ namespace Godot
|
|||
{
|
||||
public partial class Object : IDisposable
|
||||
{
|
||||
private bool disposed = false;
|
||||
private bool _disposed = false;
|
||||
|
||||
private static StringName nativeName = "Object";
|
||||
|
||||
internal IntPtr ptr;
|
||||
internal bool memoryOwn;
|
||||
internal IntPtr NativePtr;
|
||||
internal bool MemoryOwn;
|
||||
|
||||
public Object() : this(false)
|
||||
{
|
||||
if (ptr == IntPtr.Zero)
|
||||
ptr = godot_icall_Object_Ctor(this);
|
||||
if (NativePtr == IntPtr.Zero)
|
||||
{
|
||||
#if NET
|
||||
unsafe
|
||||
{
|
||||
ptr = NativeCtor();
|
||||
}
|
||||
#else
|
||||
NativePtr = _gd__invoke_class_constructor(NativeCtor);
|
||||
#endif
|
||||
NativeInterop.InteropUtils.TieManagedToUnmanaged(this, NativePtr);
|
||||
}
|
||||
|
||||
_InitializeGodotScriptInstanceInternals();
|
||||
}
|
||||
|
||||
internal void _InitializeGodotScriptInstanceInternals()
|
||||
{
|
||||
godot_icall_Object_ConnectEventSignals(ptr);
|
||||
godot_icall_Object_ConnectEventSignals(NativePtr);
|
||||
}
|
||||
|
||||
internal Object(bool memoryOwn)
|
||||
{
|
||||
this.memoryOwn = memoryOwn;
|
||||
this.MemoryOwn = memoryOwn;
|
||||
}
|
||||
|
||||
public IntPtr NativeInstance
|
||||
{
|
||||
get { return ptr; }
|
||||
}
|
||||
public IntPtr NativeInstance => NativePtr;
|
||||
|
||||
internal static IntPtr GetPtr(Object instance)
|
||||
{
|
||||
if (instance == null)
|
||||
return IntPtr.Zero;
|
||||
|
||||
if (instance.disposed)
|
||||
if (instance._disposed)
|
||||
throw new ObjectDisposedException(instance.GetType().FullName);
|
||||
|
||||
return instance.ptr;
|
||||
return instance.NativePtr;
|
||||
}
|
||||
|
||||
~Object()
|
||||
|
@ -58,25 +64,25 @@ namespace Godot
|
|||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposed)
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
if (ptr != IntPtr.Zero)
|
||||
if (NativePtr != IntPtr.Zero)
|
||||
{
|
||||
if (memoryOwn)
|
||||
if (MemoryOwn)
|
||||
{
|
||||
memoryOwn = false;
|
||||
godot_icall_RefCounted_Disposed(this, ptr, !disposing);
|
||||
MemoryOwn = false;
|
||||
godot_icall_RefCounted_Disposed(this, NativePtr, !disposing);
|
||||
}
|
||||
else
|
||||
{
|
||||
godot_icall_Object_Disposed(this, ptr);
|
||||
godot_icall_Object_Disposed(this, NativePtr);
|
||||
}
|
||||
|
||||
this.ptr = IntPtr.Zero;
|
||||
this.NativePtr = IntPtr.Zero;
|
||||
}
|
||||
|
||||
disposed = true;
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
@ -117,13 +123,49 @@ namespace Godot
|
|||
/// </summary>
|
||||
public dynamic DynamicObject => new DynamicGodotObject(this);
|
||||
|
||||
internal static IntPtr __ClassDB_get_method(StringName type, string method)
|
||||
internal static unsafe IntPtr ClassDB_get_method(StringName type, string method)
|
||||
{
|
||||
return godot_icall_Object_ClassDB_get_method(StringName.GetPtr(type), method);
|
||||
IntPtr methodBind;
|
||||
fixed (char* methodChars = method)
|
||||
{
|
||||
methodBind = NativeInterop.NativeFuncs
|
||||
.godotsharp_method_bind_get_method(ref type.NativeValue, methodChars);
|
||||
}
|
||||
|
||||
if (methodBind == IntPtr.Zero)
|
||||
throw new NativeMethodBindNotFoundException(type + "." + method);
|
||||
|
||||
return methodBind;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal static extern IntPtr godot_icall_Object_Ctor(Object obj);
|
||||
#if NET
|
||||
internal static unsafe delegate* unmanaged<IntPtr> _gd__ClassDB_get_constructor(StringName type)
|
||||
{
|
||||
// for some reason the '??' operator doesn't support 'delegate*'
|
||||
var nativeConstructor = NativeInterop.NativeFuncs
|
||||
.godotsharp_get_class_constructor(ref type.NativeValue);
|
||||
|
||||
if (nativeConstructor == null)
|
||||
throw new NativeConstructorNotFoundException(type);
|
||||
|
||||
return nativeConstructor;
|
||||
}
|
||||
#else
|
||||
internal static IntPtr ClassDB_get_constructor(StringName type)
|
||||
{
|
||||
// for some reason the '??' operator doesn't support 'delegate*'
|
||||
var nativeConstructor = NativeInterop.NativeFuncs
|
||||
.godotsharp_get_class_constructor(ref type.NativeValue);
|
||||
|
||||
if (nativeConstructor == IntPtr.Zero)
|
||||
throw new NativeConstructorNotFoundException(type);
|
||||
|
||||
return nativeConstructor;
|
||||
}
|
||||
|
||||
internal static IntPtr _gd__invoke_class_constructor(IntPtr ctorFuncPtr)
|
||||
=> NativeInterop.NativeFuncs.godotsharp_invoke_class_constructor(ctorFuncPtr);
|
||||
#endif
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal static extern void godot_icall_Object_Disposed(Object obj, IntPtr ptr);
|
||||
|
@ -136,9 +178,5 @@ namespace Godot
|
|||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal static extern string godot_icall_Object_ToString(IntPtr ptr);
|
||||
|
||||
// Used by the generated API
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal static extern IntPtr godot_icall_Object_ClassDB_get_method(IntPtr type, string method);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
using System;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Godot
|
||||
{
|
||||
public partial class Object
|
||||
{
|
||||
public class NativeMemberNotFoundException : Exception
|
||||
{
|
||||
public NativeMemberNotFoundException()
|
||||
{
|
||||
}
|
||||
|
||||
public NativeMemberNotFoundException(string? message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public NativeMemberNotFoundException(string? message, Exception? innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class NativeConstructorNotFoundException : NativeMemberNotFoundException
|
||||
{
|
||||
private readonly string? _nativeClassName;
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
private const string Arg_NativeConstructorNotFoundException = "Unable to find the native constructor.";
|
||||
|
||||
public NativeConstructorNotFoundException()
|
||||
: base(Arg_NativeConstructorNotFoundException)
|
||||
{
|
||||
}
|
||||
|
||||
public NativeConstructorNotFoundException(string? nativeClassName)
|
||||
: this(Arg_NativeConstructorNotFoundException, nativeClassName)
|
||||
{
|
||||
}
|
||||
|
||||
public NativeConstructorNotFoundException(string? message, Exception? innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
public NativeConstructorNotFoundException(string? message, string? nativeClassName)
|
||||
: base(message)
|
||||
{
|
||||
_nativeClassName = nativeClassName;
|
||||
}
|
||||
|
||||
public NativeConstructorNotFoundException(string? message, string? nativeClassName, Exception? innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
_nativeClassName = nativeClassName;
|
||||
}
|
||||
|
||||
public override string Message
|
||||
{
|
||||
get
|
||||
{
|
||||
string s = base.Message;
|
||||
|
||||
if (string.IsNullOrEmpty(s))
|
||||
{
|
||||
s = Arg_NativeConstructorNotFoundException;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(_nativeClassName))
|
||||
{
|
||||
s += " " + string.Format("(Class '{0}')", _nativeClassName);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class NativeMethodBindNotFoundException : NativeMemberNotFoundException
|
||||
{
|
||||
private readonly string? _nativeMethodName;
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
private const string Arg_NativeMethodBindNotFoundException = "Unable to find the native method bind.";
|
||||
|
||||
public NativeMethodBindNotFoundException()
|
||||
: base(Arg_NativeMethodBindNotFoundException)
|
||||
{
|
||||
}
|
||||
|
||||
public NativeMethodBindNotFoundException(string? nativeMethodName)
|
||||
: this(Arg_NativeMethodBindNotFoundException, nativeMethodName)
|
||||
{
|
||||
}
|
||||
|
||||
public NativeMethodBindNotFoundException(string? message, Exception? innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
public NativeMethodBindNotFoundException(string? message, string? nativeMethodName)
|
||||
: base(message)
|
||||
{
|
||||
_nativeMethodName = nativeMethodName;
|
||||
}
|
||||
|
||||
public NativeMethodBindNotFoundException(string? message, string? nativeMethodName, Exception? innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
_nativeMethodName = nativeMethodName;
|
||||
}
|
||||
|
||||
public override string Message
|
||||
{
|
||||
get
|
||||
{
|
||||
string s = base.Message;
|
||||
|
||||
if (string.IsNullOrEmpty(s))
|
||||
{
|
||||
s = Arg_NativeMethodBindNotFoundException;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(_nativeMethodName))
|
||||
{
|
||||
s += " " + string.Format("(Method '{0}')", _nativeMethodName);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,84 +1,25 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
namespace Godot
|
||||
{
|
||||
public sealed partial class RID : IDisposable
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct RID
|
||||
{
|
||||
private bool disposed = false;
|
||||
private ulong _id; // Default is 0
|
||||
|
||||
internal IntPtr ptr;
|
||||
|
||||
internal static IntPtr GetPtr(RID instance)
|
||||
internal RID(ulong id)
|
||||
{
|
||||
if (instance == null)
|
||||
throw new NullReferenceException($"The instance of type {nameof(RID)} is null.");
|
||||
|
||||
if (instance.disposed)
|
||||
throw new ObjectDisposedException(instance.GetType().FullName);
|
||||
|
||||
return instance.ptr;
|
||||
}
|
||||
|
||||
~RID()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (disposed)
|
||||
return;
|
||||
|
||||
if (ptr != IntPtr.Zero)
|
||||
{
|
||||
godot_icall_RID_Dtor(ptr);
|
||||
ptr = IntPtr.Zero;
|
||||
}
|
||||
|
||||
disposed = true;
|
||||
}
|
||||
|
||||
internal RID(IntPtr ptr)
|
||||
{
|
||||
this.ptr = ptr;
|
||||
}
|
||||
|
||||
public IntPtr NativeInstance
|
||||
{
|
||||
get { return ptr; }
|
||||
}
|
||||
|
||||
internal RID()
|
||||
{
|
||||
this.ptr = IntPtr.Zero;
|
||||
_id = id;
|
||||
}
|
||||
|
||||
public RID(Object from)
|
||||
{
|
||||
this.ptr = godot_icall_RID_Ctor(Object.GetPtr(from));
|
||||
}
|
||||
=> _id = from is Resource res ? res.GetRid()._id : default;
|
||||
|
||||
public int GetId()
|
||||
{
|
||||
return godot_icall_RID_get_id(RID.GetPtr(this));
|
||||
}
|
||||
public ulong Id => _id;
|
||||
|
||||
public override string ToString() => "[RID]";
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static IntPtr godot_icall_RID_Ctor(IntPtr from);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_RID_Dtor(IntPtr ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static int godot_icall_RID_get_id(IntPtr ptr);
|
||||
public override string ToString() => $"RID({Id})";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,53 +1,42 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
namespace Godot
|
||||
{
|
||||
public class SignalAwaiter : IAwaiter<object[]>, IAwaitable<object[]>
|
||||
{
|
||||
private bool completed;
|
||||
private object[] result;
|
||||
private Action action;
|
||||
private bool _completed;
|
||||
private object[] _result;
|
||||
private Action _action;
|
||||
|
||||
public SignalAwaiter(Object source, StringName signal, Object target)
|
||||
{
|
||||
godot_icall_SignalAwaiter_connect(Object.GetPtr(source), StringName.GetPtr(signal), Object.GetPtr(target), this);
|
||||
godot_icall_SignalAwaiter_connect(Object.GetPtr(source), ref signal.NativeValue, Object.GetPtr(target), this);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static Error godot_icall_SignalAwaiter_connect(IntPtr source, IntPtr signal, IntPtr target, SignalAwaiter awaiter);
|
||||
internal static extern Error godot_icall_SignalAwaiter_connect(IntPtr source, ref godot_string_name signal, IntPtr target, SignalAwaiter awaiter);
|
||||
|
||||
public bool IsCompleted
|
||||
{
|
||||
get
|
||||
{
|
||||
return completed;
|
||||
}
|
||||
}
|
||||
public bool IsCompleted => _completed;
|
||||
|
||||
public void OnCompleted(Action action)
|
||||
{
|
||||
this.action = action;
|
||||
this._action = action;
|
||||
}
|
||||
|
||||
public object[] GetResult()
|
||||
{
|
||||
return result;
|
||||
}
|
||||
public object[] GetResult() => _result;
|
||||
|
||||
public IAwaiter<object[]> GetAwaiter()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
public IAwaiter<object[]> GetAwaiter() => this;
|
||||
|
||||
internal void SignalCallback(object[] args)
|
||||
{
|
||||
completed = true;
|
||||
result = args;
|
||||
_completed = true;
|
||||
_result = args;
|
||||
|
||||
if (action != null)
|
||||
if (_action != null)
|
||||
{
|
||||
action();
|
||||
_action();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -192,7 +192,7 @@ namespace Godot
|
|||
/// </summary>
|
||||
public static string CEscape(this string instance)
|
||||
{
|
||||
var sb = new StringBuilder(string.Copy(instance));
|
||||
var sb = new StringBuilder(instance);
|
||||
|
||||
sb.Replace("\\", "\\\\");
|
||||
sb.Replace("\a", "\\a");
|
||||
|
@ -215,7 +215,7 @@ namespace Godot
|
|||
/// </summary>
|
||||
public static string CUnescape(this string instance)
|
||||
{
|
||||
var sb = new StringBuilder(string.Copy(instance));
|
||||
var sb = new StringBuilder(instance);
|
||||
|
||||
sb.Replace("\\a", "\a");
|
||||
sb.Replace("\\b", "\b");
|
||||
|
@ -732,7 +732,7 @@ namespace Godot
|
|||
/// </summary>
|
||||
public static string JSONEscape(this string instance)
|
||||
{
|
||||
var sb = new StringBuilder(string.Copy(instance));
|
||||
var sb = new StringBuilder(instance);
|
||||
|
||||
sb.Replace("\\", "\\\\");
|
||||
sb.Replace("\b", "\\b");
|
||||
|
|
|
@ -1,22 +1,12 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
namespace Godot
|
||||
{
|
||||
public sealed partial class StringName : IDisposable
|
||||
public sealed class StringName : IDisposable
|
||||
{
|
||||
private IntPtr ptr;
|
||||
|
||||
internal static IntPtr GetPtr(StringName instance)
|
||||
{
|
||||
if (instance == null)
|
||||
throw new NullReferenceException($"The instance of type {nameof(StringName)} is null.");
|
||||
|
||||
if (instance.ptr == IntPtr.Zero)
|
||||
throw new ObjectDisposedException(instance.GetType().FullName);
|
||||
|
||||
return instance.ptr;
|
||||
}
|
||||
internal godot_string_name NativeValue;
|
||||
|
||||
~StringName()
|
||||
{
|
||||
|
@ -29,54 +19,47 @@ namespace Godot
|
|||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
public void Dispose(bool disposing)
|
||||
{
|
||||
if (ptr != IntPtr.Zero)
|
||||
{
|
||||
godot_icall_StringName_Dtor(ptr);
|
||||
ptr = IntPtr.Zero;
|
||||
}
|
||||
// Always dispose `NativeValue` even if disposing is true
|
||||
NativeValue.Dispose();
|
||||
}
|
||||
|
||||
internal StringName(IntPtr ptr)
|
||||
private StringName(godot_string_name nativeValueToOwn)
|
||||
{
|
||||
this.ptr = ptr;
|
||||
NativeValue = nativeValueToOwn;
|
||||
}
|
||||
|
||||
// Explicit name to make it very clear
|
||||
internal static StringName CreateTakingOwnershipOfDisposableValue(godot_string_name nativeValueToOwn)
|
||||
=> new StringName(nativeValueToOwn);
|
||||
|
||||
public StringName()
|
||||
{
|
||||
ptr = IntPtr.Zero;
|
||||
}
|
||||
|
||||
public StringName(string path)
|
||||
public StringName(string name)
|
||||
{
|
||||
ptr = path == null ? IntPtr.Zero : godot_icall_StringName_Ctor(path);
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
NativeValue = NativeFuncs.godotsharp_string_name_new_from_string(name);
|
||||
}
|
||||
|
||||
public static implicit operator StringName(string from) => new StringName(from);
|
||||
|
||||
public static implicit operator string(StringName from) => from.ToString();
|
||||
|
||||
public override string ToString()
|
||||
public override unsafe string ToString()
|
||||
{
|
||||
return ptr == IntPtr.Zero ? string.Empty : godot_icall_StringName_operator_String(GetPtr(this));
|
||||
if (IsEmpty)
|
||||
return string.Empty;
|
||||
|
||||
godot_string dest;
|
||||
godot_string_name src = NativeValue;
|
||||
NativeFuncs.godotsharp_string_name_as_string(&dest, &src);
|
||||
using (dest)
|
||||
return Marshaling.mono_string_from_godot(&dest);
|
||||
}
|
||||
|
||||
public bool IsEmpty()
|
||||
{
|
||||
return ptr == IntPtr.Zero || godot_icall_StringName_is_empty(GetPtr(this));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern IntPtr godot_icall_StringName_Ctor(string path);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern void godot_icall_StringName_Dtor(IntPtr ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string godot_icall_StringName_operator_String(IntPtr ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern bool godot_icall_StringName_is_empty(IntPtr ptr);
|
||||
public bool IsEmpty => godot_string_name.IsEmpty(in NativeValue);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,10 +7,19 @@
|
|||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<DocumentationFile>$(OutputPath)/$(AssemblyName).xml</DocumentationFile>
|
||||
<EnableDefaultItems>false</EnableDefaultItems>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<LangVersion>9</LangVersion>
|
||||
|
||||
<!-- Disabled temporarily as it pollutes the warnings, but we need to document public APIs. -->
|
||||
<NoWarn>CS1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<DefineConstants>$(DefineConstants);GODOT</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>
|
||||
<Compile Include="Core\AABB.cs" />
|
||||
<Compile Include="Core\Array.cs" />
|
||||
|
@ -44,16 +53,23 @@
|
|||
<Compile Include="Core\Interfaces\IAwaitable.cs" />
|
||||
<Compile Include="Core\Interfaces\IAwaiter.cs" />
|
||||
<Compile Include="Core\Interfaces\ISerializationListener.cs" />
|
||||
<Compile Include="Core\MarshalUtils.cs" />
|
||||
<Compile Include="Core\Mathf.cs" />
|
||||
<Compile Include="Core\MathfEx.cs" />
|
||||
<Compile Include="Core\NativeInterop\InteropUtils.cs" />
|
||||
<Compile Include="Core\NativeInterop\NativeFuncs.extended.cs" />
|
||||
<Compile Include="Core\NativeInterop\VariantSpanHelpers.cs" />
|
||||
<Compile Include="Core\NativeInterop\VariantUtils.cs" />
|
||||
<Compile Include="Core\NodePath.cs" />
|
||||
<Compile Include="Core\Object.base.cs" />
|
||||
<Compile Include="Core\Object.exceptions.cs" />
|
||||
<Compile Include="Core\Plane.cs" />
|
||||
<Compile Include="Core\Quaternion.cs" />
|
||||
<Compile Include="Core\Rect2.cs" />
|
||||
<Compile Include="Core\Rect2i.cs" />
|
||||
<Compile Include="Core\RID.cs" />
|
||||
<Compile Include="Core\NativeInterop\NativeFuncs.cs" />
|
||||
<Compile Include="Core\NativeInterop\InteropStructs.cs" />
|
||||
<Compile Include="Core\NativeInterop\Marshaling.cs" />
|
||||
<Compile Include="Core\SignalInfo.cs" />
|
||||
<Compile Include="Core\SignalAwaiter.cs" />
|
||||
<Compile Include="Core\StringExtensions.cs" />
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=core/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=generated/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=generated_005Cgodotobjects/@EntryIndexedValue">True</s:Boolean>
|
||||
</wpf:ResourceDictionary>
|
|
@ -7,6 +7,8 @@
|
|||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<DocumentationFile>$(OutputPath)/$(AssemblyName).xml</DocumentationFile>
|
||||
<EnableDefaultItems>false</EnableDefaultItems>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<LangVersion>9</LangVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<DefineConstants>$(DefineConstants);GODOT</DefineConstants>
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=generated/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=generated_005Cgodotobjects/@EntryIndexedValue">True</s:Boolean>
|
||||
</wpf:ResourceDictionary>
|
|
@ -28,8 +28,6 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef MONO_GLUE_ENABLED
|
||||
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/object/ref_counted.h"
|
||||
#include "core/string/string_name.h"
|
||||
|
@ -43,12 +41,6 @@
|
|||
#include "../signal_awaiter_utils.h"
|
||||
#include "arguments_vector.h"
|
||||
|
||||
Object *godot_icall_Object_Ctor(MonoObject *p_obj) {
|
||||
Object *instance = memnew(Object);
|
||||
GDMonoInternals::tie_managed_to_unmanaged(p_obj, instance);
|
||||
return instance;
|
||||
}
|
||||
|
||||
void godot_icall_Object_Disposed(MonoObject *p_obj, Object *p_ptr) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
CRASH_COND(p_ptr == nullptr);
|
||||
|
@ -133,12 +125,6 @@ void godot_icall_Object_ConnectEventSignals(Object *p_ptr) {
|
|||
}
|
||||
}
|
||||
|
||||
MethodBind *godot_icall_Object_ClassDB_get_method(StringName *p_type, MonoString *p_method) {
|
||||
StringName type = p_type ? *p_type : StringName();
|
||||
StringName method(GDMonoMarshal::mono_string_to_godot(p_method));
|
||||
return ClassDB::get_method(type, method);
|
||||
}
|
||||
|
||||
MonoObject *godot_icall_Object_weakref(Object *p_ptr) {
|
||||
if (!p_ptr) {
|
||||
return nullptr;
|
||||
|
@ -240,11 +226,9 @@ MonoString *godot_icall_Object_ToString(Object *p_ptr) {
|
|||
}
|
||||
|
||||
void godot_register_object_icalls() {
|
||||
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_Ctor", godot_icall_Object_Ctor);
|
||||
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_Disposed", godot_icall_Object_Disposed);
|
||||
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_RefCounted_Disposed", godot_icall_RefCounted_Disposed);
|
||||
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_ConnectEventSignals", godot_icall_Object_ConnectEventSignals);
|
||||
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_ClassDB_get_method", godot_icall_Object_ClassDB_get_method);
|
||||
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_ToString", godot_icall_Object_ToString);
|
||||
GDMonoUtils::add_internal_call("Godot.Object::godot_icall_Object_weakref", godot_icall_Object_weakref);
|
||||
GDMonoUtils::add_internal_call("Godot.SignalAwaiter::godot_icall_SignalAwaiter_connect", godot_icall_SignalAwaiter_connect);
|
||||
|
@ -253,5 +237,3 @@ void godot_register_object_icalls() {
|
|||
GDMonoUtils::add_internal_call("Godot.DynamicGodotObject::godot_icall_DynamicGodotObject_GetMember", godot_icall_DynamicGodotObject_GetMember);
|
||||
GDMonoUtils::add_internal_call("Godot.DynamicGodotObject::godot_icall_DynamicGodotObject_SetMember", godot_icall_DynamicGodotObject_SetMember);
|
||||
}
|
||||
|
||||
#endif // MONO_GLUE_ENABLED
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef MONO_GLUE_ENABLED
|
||||
|
||||
#include <mono/metadata/exception.h>
|
||||
|
||||
#include "core/variant/array.h"
|
||||
|
@ -39,28 +37,17 @@
|
|||
#include "../mono_gd/gd_mono_marshal.h"
|
||||
#include "../mono_gd/gd_mono_utils.h"
|
||||
|
||||
Array *godot_icall_Array_Ctor() {
|
||||
return memnew(Array);
|
||||
void godot_icall_Array_Ctor(Array *r_dest) {
|
||||
memnew_placement(r_dest, Array);
|
||||
}
|
||||
|
||||
void godot_icall_Array_Dtor(Array *ptr) {
|
||||
memdelete(ptr);
|
||||
}
|
||||
|
||||
MonoObject *godot_icall_Array_At(Array *ptr, int32_t index) {
|
||||
void godot_icall_Array_At(Array *ptr, int32_t index, Variant *r_elem) {
|
||||
if (index < 0 || index >= ptr->size()) {
|
||||
GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range());
|
||||
return nullptr;
|
||||
*r_elem = Variant();
|
||||
return;
|
||||
}
|
||||
return GDMonoMarshal::variant_to_mono_object(ptr->operator[](index));
|
||||
}
|
||||
|
||||
MonoObject *godot_icall_Array_At_Generic(Array *ptr, int32_t index, uint32_t type_encoding, GDMonoClass *type_class) {
|
||||
if (index < 0 || index >= ptr->size()) {
|
||||
GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range());
|
||||
return nullptr;
|
||||
}
|
||||
return GDMonoMarshal::variant_to_mono_object(ptr->operator[](index), ManagedType(type_encoding, type_class));
|
||||
*r_elem = ptr->operator[](index);
|
||||
}
|
||||
|
||||
void godot_icall_Array_SetAt(Array *ptr, int32_t index, MonoObject *value) {
|
||||
|
@ -104,29 +91,27 @@ void godot_icall_Array_CopyTo(Array *ptr, MonoArray *array, int32_t array_index)
|
|||
}
|
||||
}
|
||||
|
||||
Array *godot_icall_Array_Ctor_MonoArray(MonoArray *mono_array) {
|
||||
Array *godot_array = memnew(Array);
|
||||
void godot_icall_Array_Ctor_MonoArray(MonoArray *mono_array, Array *r_dest) {
|
||||
memnew_placement(r_dest, Array);
|
||||
unsigned int count = mono_array_length(mono_array);
|
||||
godot_array->resize(count);
|
||||
r_dest->resize(count);
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
MonoObject *item = mono_array_get(mono_array, MonoObject *, i);
|
||||
godot_icall_Array_SetAt(godot_array, i, item);
|
||||
godot_icall_Array_SetAt(r_dest, i, item);
|
||||
}
|
||||
return godot_array;
|
||||
}
|
||||
|
||||
Array *godot_icall_Array_Duplicate(Array *ptr, MonoBoolean deep) {
|
||||
return memnew(Array(ptr->duplicate(deep)));
|
||||
void godot_icall_Array_Duplicate(Array *ptr, MonoBoolean deep, Array *r_dest) {
|
||||
memnew_placement(r_dest, Array(ptr->duplicate(deep)));
|
||||
}
|
||||
|
||||
Array *godot_icall_Array_Concatenate(Array *left, Array *right) {
|
||||
void godot_icall_Array_Concatenate(Array *left, Array *right, Array *r_dest) {
|
||||
int count = left->size() + right->size();
|
||||
Array *new_array = memnew(Array(left->duplicate(false)));
|
||||
new_array->resize(count);
|
||||
memnew_placement(r_dest, Array(left->duplicate(false)));
|
||||
r_dest->resize(count);
|
||||
for (unsigned int i = 0; i < (unsigned int)right->size(); i++) {
|
||||
new_array->operator[](i + left->size()) = right->operator[](i);
|
||||
r_dest->operator[](i + left->size()) = right->operator[](i);
|
||||
}
|
||||
return new_array;
|
||||
}
|
||||
|
||||
int32_t godot_icall_Array_IndexOf(Array *ptr, MonoObject *item) {
|
||||
|
@ -166,27 +151,15 @@ void godot_icall_Array_Shuffle(Array *ptr) {
|
|||
ptr->shuffle();
|
||||
}
|
||||
|
||||
void godot_icall_Array_Generic_GetElementTypeInfo(MonoReflectionType *refltype, uint32_t *type_encoding, GDMonoClass **type_class) {
|
||||
MonoType *elem_type = mono_reflection_type_get_type(refltype);
|
||||
|
||||
*type_encoding = mono_type_get_type(elem_type);
|
||||
MonoClass *type_class_raw = mono_class_from_mono_type(elem_type);
|
||||
*type_class = GDMono::get_singleton()->get_class(type_class_raw);
|
||||
}
|
||||
|
||||
MonoString *godot_icall_Array_ToString(Array *ptr) {
|
||||
return GDMonoMarshal::mono_string_from_godot(Variant(*ptr).operator String());
|
||||
}
|
||||
|
||||
Dictionary *godot_icall_Dictionary_Ctor() {
|
||||
return memnew(Dictionary);
|
||||
void godot_icall_Dictionary_Ctor(Dictionary *r_dest) {
|
||||
memnew_placement(r_dest, Dictionary);
|
||||
}
|
||||
|
||||
void godot_icall_Dictionary_Dtor(Dictionary *ptr) {
|
||||
memdelete(ptr);
|
||||
}
|
||||
|
||||
MonoObject *godot_icall_Dictionary_GetValue(Dictionary *ptr, MonoObject *key) {
|
||||
void godot_icall_Dictionary_GetValue(Dictionary *ptr, MonoObject *key, Variant *r_value) {
|
||||
Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
|
||||
if (ret == nullptr) {
|
||||
MonoObject *exc = mono_object_new(mono_domain_get(), CACHED_CLASS(KeyNotFoundException)->get_mono_ptr());
|
||||
|
@ -195,35 +168,22 @@ MonoObject *godot_icall_Dictionary_GetValue(Dictionary *ptr, MonoObject *key) {
|
|||
#endif
|
||||
GDMonoUtils::runtime_object_init(exc, CACHED_CLASS(KeyNotFoundException));
|
||||
GDMonoUtils::set_pending_exception((MonoException *)exc);
|
||||
return nullptr;
|
||||
*r_value = Variant();
|
||||
return;
|
||||
}
|
||||
return GDMonoMarshal::variant_to_mono_object(ret);
|
||||
}
|
||||
|
||||
MonoObject *godot_icall_Dictionary_GetValue_Generic(Dictionary *ptr, MonoObject *key, uint32_t type_encoding, GDMonoClass *type_class) {
|
||||
Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
|
||||
if (ret == nullptr) {
|
||||
MonoObject *exc = mono_object_new(mono_domain_get(), CACHED_CLASS(KeyNotFoundException)->get_mono_ptr());
|
||||
#ifdef DEBUG_ENABLED
|
||||
CRASH_COND(!exc);
|
||||
#endif
|
||||
GDMonoUtils::runtime_object_init(exc, CACHED_CLASS(KeyNotFoundException));
|
||||
GDMonoUtils::set_pending_exception((MonoException *)exc);
|
||||
return nullptr;
|
||||
}
|
||||
return GDMonoMarshal::variant_to_mono_object(ret, ManagedType(type_encoding, type_class));
|
||||
*r_value = ret;
|
||||
}
|
||||
|
||||
void godot_icall_Dictionary_SetValue(Dictionary *ptr, MonoObject *key, MonoObject *value) {
|
||||
ptr->operator[](GDMonoMarshal::mono_object_to_variant(key)) = GDMonoMarshal::mono_object_to_variant(value);
|
||||
}
|
||||
|
||||
Array *godot_icall_Dictionary_Keys(Dictionary *ptr) {
|
||||
return memnew(Array(ptr->keys()));
|
||||
void godot_icall_Dictionary_Keys(Dictionary *ptr, Array *r_dest) {
|
||||
memnew_placement(r_dest, Array(ptr->keys()));
|
||||
}
|
||||
|
||||
Array *godot_icall_Dictionary_Values(Dictionary *ptr) {
|
||||
return memnew(Array(ptr->values()));
|
||||
void godot_icall_Dictionary_Values(Dictionary *ptr, Array *r_dest) {
|
||||
memnew_placement(r_dest, Array(ptr->values()));
|
||||
}
|
||||
|
||||
int32_t godot_icall_Dictionary_Count(Dictionary *ptr) {
|
||||
|
@ -231,16 +191,14 @@ int32_t godot_icall_Dictionary_Count(Dictionary *ptr) {
|
|||
}
|
||||
|
||||
int32_t godot_icall_Dictionary_KeyValuePairs(Dictionary *ptr, Array **keys, Array **values) {
|
||||
*keys = godot_icall_Dictionary_Keys(ptr);
|
||||
*values = godot_icall_Dictionary_Values(ptr);
|
||||
return godot_icall_Dictionary_Count(ptr);
|
||||
memnew_placement(*keys, Array(ptr->keys()));
|
||||
memnew_placement(*values, Array(ptr->values()));
|
||||
return ptr->size();
|
||||
}
|
||||
|
||||
void godot_icall_Dictionary_KeyValuePairAt(Dictionary *ptr, int index, MonoObject **key, MonoObject **value) {
|
||||
Array *keys = godot_icall_Dictionary_Keys(ptr);
|
||||
Array *values = godot_icall_Dictionary_Values(ptr);
|
||||
*key = GDMonoMarshal::variant_to_mono_object(keys->get(index));
|
||||
*value = GDMonoMarshal::variant_to_mono_object(values->get(index));
|
||||
*key = GDMonoMarshal::variant_to_mono_object(ptr->get_key_at_index(index));
|
||||
*value = GDMonoMarshal::variant_to_mono_object(ptr->get_value_at_index(index));
|
||||
}
|
||||
|
||||
void godot_icall_Dictionary_Add(Dictionary *ptr, MonoObject *key, MonoObject *value) {
|
||||
|
@ -267,8 +225,8 @@ MonoBoolean godot_icall_Dictionary_ContainsKey(Dictionary *ptr, MonoObject *key)
|
|||
return ptr->has(GDMonoMarshal::mono_object_to_variant(key));
|
||||
}
|
||||
|
||||
Dictionary *godot_icall_Dictionary_Duplicate(Dictionary *ptr, MonoBoolean deep) {
|
||||
return memnew(Dictionary(ptr->duplicate(deep)));
|
||||
void godot_icall_Dictionary_Duplicate(Dictionary *ptr, MonoBoolean deep, Dictionary *r_dest) {
|
||||
memnew_placement(r_dest, Dictionary(ptr->duplicate(deep)));
|
||||
}
|
||||
|
||||
MonoBoolean godot_icall_Dictionary_RemoveKey(Dictionary *ptr, MonoObject *key) {
|
||||
|
@ -288,34 +246,16 @@ MonoBoolean godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, Mono
|
|||
return false;
|
||||
}
|
||||
|
||||
MonoBoolean godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoObject **value) {
|
||||
MonoBoolean godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, Variant *value) {
|
||||
Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
|
||||
if (ret == nullptr) {
|
||||
*value = nullptr;
|
||||
*value = Variant();
|
||||
return false;
|
||||
}
|
||||
*value = GDMonoMarshal::variant_to_mono_object(ret);
|
||||
*value = ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
MonoBoolean godot_icall_Dictionary_TryGetValue_Generic(Dictionary *ptr, MonoObject *key, MonoObject **value, uint32_t type_encoding, GDMonoClass *type_class) {
|
||||
Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
|
||||
if (ret == nullptr) {
|
||||
*value = nullptr;
|
||||
return false;
|
||||
}
|
||||
*value = GDMonoMarshal::variant_to_mono_object(ret, ManagedType(type_encoding, type_class));
|
||||
return true;
|
||||
}
|
||||
|
||||
void godot_icall_Dictionary_Generic_GetValueTypeInfo(MonoReflectionType *refltype, uint32_t *type_encoding, GDMonoClass **type_class) {
|
||||
MonoType *value_type = mono_reflection_type_get_type(refltype);
|
||||
|
||||
*type_encoding = mono_type_get_type(value_type);
|
||||
MonoClass *type_class_raw = mono_class_from_mono_type(value_type);
|
||||
*type_class = GDMono::get_singleton()->get_class(type_class_raw);
|
||||
}
|
||||
|
||||
MonoString *godot_icall_Dictionary_ToString(Dictionary *ptr) {
|
||||
return GDMonoMarshal::mono_string_from_godot(Variant(*ptr).operator String());
|
||||
}
|
||||
|
@ -323,9 +263,7 @@ MonoString *godot_icall_Dictionary_ToString(Dictionary *ptr) {
|
|||
void godot_register_collections_icalls() {
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Ctor", godot_icall_Array_Ctor);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Ctor_MonoArray", godot_icall_Array_Ctor_MonoArray);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Dtor", godot_icall_Array_Dtor);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_At", godot_icall_Array_At);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_At_Generic", godot_icall_Array_At_Generic);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_SetAt", godot_icall_Array_SetAt);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Count", godot_icall_Array_Count);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Add", godot_icall_Array_Add);
|
||||
|
@ -340,13 +278,10 @@ void godot_register_collections_icalls() {
|
|||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_RemoveAt", godot_icall_Array_RemoveAt);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Resize", godot_icall_Array_Resize);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Shuffle", godot_icall_Array_Shuffle);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Generic_GetElementTypeInfo", godot_icall_Array_Generic_GetElementTypeInfo);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_ToString", godot_icall_Array_ToString);
|
||||
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Ctor", godot_icall_Dictionary_Ctor);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Dtor", godot_icall_Dictionary_Dtor);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_GetValue", godot_icall_Dictionary_GetValue);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_GetValue_Generic", godot_icall_Dictionary_GetValue_Generic);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_SetValue", godot_icall_Dictionary_SetValue);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Keys", godot_icall_Dictionary_Keys);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Values", godot_icall_Dictionary_Values);
|
||||
|
@ -361,9 +296,5 @@ void godot_register_collections_icalls() {
|
|||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_RemoveKey", godot_icall_Dictionary_RemoveKey);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Remove", godot_icall_Dictionary_Remove);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_TryGetValue", godot_icall_Dictionary_TryGetValue);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_TryGetValue_Generic", godot_icall_Dictionary_TryGetValue_Generic);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Generic_GetValueTypeInfo", godot_icall_Dictionary_Generic_GetValueTypeInfo);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_ToString", godot_icall_Dictionary_ToString);
|
||||
}
|
||||
|
||||
#endif // MONO_GLUE_ENABLED
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef MONO_GLUE_ENABLED
|
||||
|
||||
#include "core/io/marshalls.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/string/ustring.h"
|
||||
|
@ -41,10 +39,9 @@
|
|||
#include "../mono_gd/gd_mono_marshal.h"
|
||||
#include "../mono_gd/gd_mono_utils.h"
|
||||
|
||||
MonoObject *godot_icall_GD_bytes2var(MonoArray *p_bytes, MonoBoolean p_allow_objects) {
|
||||
MonoObject *godot_icall_GD_bytes2var(PackedByteArray *p_bytes, MonoBoolean p_allow_objects) {
|
||||
Variant ret;
|
||||
PackedByteArray varr = GDMonoMarshal::mono_array_to_PackedByteArray(p_bytes);
|
||||
Error err = decode_variant(ret, varr.ptr(), varr.size(), nullptr, p_allow_objects);
|
||||
Error err = decode_variant(ret, p_bytes->ptr(), p_bytes->size(), nullptr, p_allow_objects);
|
||||
if (err != OK) {
|
||||
ret = RTR("Not enough bytes for decoding bytes, or invalid format.");
|
||||
}
|
||||
|
@ -260,18 +257,17 @@ void godot_icall_GD_pushwarning(MonoString *p_str) {
|
|||
WARN_PRINT(GDMonoMarshal::mono_string_to_godot(p_str));
|
||||
}
|
||||
|
||||
MonoArray *godot_icall_GD_var2bytes(MonoObject *p_var, MonoBoolean p_full_objects) {
|
||||
void godot_icall_GD_var2bytes(MonoObject *p_var, MonoBoolean p_full_objects, PackedByteArray *r_bytes) {
|
||||
memnew_placement(r_bytes, PackedByteArray);
|
||||
|
||||
Variant var = GDMonoMarshal::mono_object_to_variant(p_var);
|
||||
|
||||
PackedByteArray barr;
|
||||
int len;
|
||||
Error err = encode_variant(var, nullptr, len, p_full_objects);
|
||||
ERR_FAIL_COND_V_MSG(err != OK, nullptr, "Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID).");
|
||||
ERR_FAIL_COND_MSG(err != OK, "Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID).");
|
||||
|
||||
barr.resize(len);
|
||||
encode_variant(var, barr.ptrw(), len, p_full_objects);
|
||||
|
||||
return GDMonoMarshal::PackedByteArray_to_mono_array(barr);
|
||||
r_bytes->resize(len);
|
||||
encode_variant(var, r_bytes->ptrw(), len, p_full_objects);
|
||||
}
|
||||
|
||||
MonoString *godot_icall_GD_var2str(MonoObject *p_var) {
|
||||
|
@ -317,5 +313,3 @@ void godot_register_gd_icalls() {
|
|||
// Dispatcher
|
||||
GDMonoUtils::add_internal_call("Godot.Dispatcher::godot_icall_DefaultGodotTaskScheduler", godot_icall_DefaultGodotTaskScheduler);
|
||||
}
|
||||
|
||||
#endif // MONO_GLUE_ENABLED
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* glue_header.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef MONO_GLUE_ENABLED
|
||||
|
||||
#include "../mono_gd/gd_mono_marshal.h"
|
||||
|
||||
void godot_register_collections_icalls();
|
||||
void godot_register_gd_icalls();
|
||||
void godot_register_string_name_icalls();
|
||||
void godot_register_nodepath_icalls();
|
||||
void godot_register_object_icalls();
|
||||
void godot_register_rid_icalls();
|
||||
void godot_register_string_icalls();
|
||||
void godot_register_scene_tree_icalls();
|
||||
|
||||
/**
|
||||
* Registers internal calls that were not generated. This function is called
|
||||
* from the generated GodotSharpBindings::register_generated_icalls() function.
|
||||
*/
|
||||
void godot_register_glue_header_icalls() {
|
||||
godot_register_collections_icalls();
|
||||
godot_register_gd_icalls();
|
||||
godot_register_string_name_icalls();
|
||||
godot_register_nodepath_icalls();
|
||||
godot_register_object_icalls();
|
||||
godot_register_rid_icalls();
|
||||
godot_register_string_icalls();
|
||||
godot_register_scene_tree_icalls();
|
||||
}
|
||||
|
||||
// Used by the generated glue
|
||||
|
||||
#include "core/config/engine.h"
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/object/method_bind.h"
|
||||
#include "core/object/ref_counted.h"
|
||||
#include "core/string/node_path.h"
|
||||
#include "core/string/ustring.h"
|
||||
#include "core/typedefs.h"
|
||||
#include "core/variant/array.h"
|
||||
#include "core/variant/dictionary.h"
|
||||
|
||||
#include "../mono_gd/gd_mono_class.h"
|
||||
#include "../mono_gd/gd_mono_internals.h"
|
||||
#include "../mono_gd/gd_mono_utils.h"
|
||||
|
||||
#define GODOTSHARP_INSTANCE_OBJECT(m_instance, m_type) \
|
||||
static ClassDB::ClassInfo *ci = nullptr; \
|
||||
if (!ci) { \
|
||||
ci = ClassDB::classes.getptr(m_type); \
|
||||
} \
|
||||
Object *m_instance = ci->creation_func();
|
||||
|
||||
#include "arguments_vector.h"
|
||||
|
||||
#endif // MONO_GLUE_ENABLED
|
|
@ -1,5 +1,5 @@
|
|||
/*************************************************************************/
|
||||
/* nodepath_glue.cpp */
|
||||
/* node_path_glue.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
|
@ -28,26 +28,11 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef MONO_GLUE_ENABLED
|
||||
|
||||
#include "core/string/node_path.h"
|
||||
#include "core/string/ustring.h"
|
||||
|
||||
#include "../mono_gd/gd_mono_marshal.h"
|
||||
|
||||
NodePath *godot_icall_NodePath_Ctor(MonoString *p_path) {
|
||||
return memnew(NodePath(GDMonoMarshal::mono_string_to_godot(p_path)));
|
||||
}
|
||||
|
||||
void godot_icall_NodePath_Dtor(NodePath *p_ptr) {
|
||||
ERR_FAIL_NULL(p_ptr);
|
||||
memdelete(p_ptr);
|
||||
}
|
||||
|
||||
MonoString *godot_icall_NodePath_operator_String(NodePath *p_np) {
|
||||
return GDMonoMarshal::mono_string_from_godot(p_np->operator String());
|
||||
}
|
||||
|
||||
MonoBoolean godot_icall_NodePath_is_absolute(NodePath *p_ptr) {
|
||||
return (MonoBoolean)p_ptr->is_absolute();
|
||||
}
|
||||
|
@ -72,18 +57,11 @@ MonoString *godot_icall_NodePath_get_concatenated_subnames(NodePath *p_ptr) {
|
|||
return GDMonoMarshal::mono_string_from_godot(p_ptr->get_concatenated_subnames());
|
||||
}
|
||||
|
||||
NodePath *godot_icall_NodePath_get_as_property_path(NodePath *p_ptr) {
|
||||
return memnew(NodePath(p_ptr->get_as_property_path()));
|
||||
void godot_icall_NodePath_get_as_property_path(NodePath *p_ptr, NodePath *r_dest) {
|
||||
*r_dest = p_ptr->get_as_property_path();
|
||||
}
|
||||
|
||||
MonoBoolean godot_icall_NodePath_is_empty(NodePath *p_ptr) {
|
||||
return (MonoBoolean)p_ptr->is_empty();
|
||||
}
|
||||
|
||||
void godot_register_nodepath_icalls() {
|
||||
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_Ctor", godot_icall_NodePath_Ctor);
|
||||
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_Dtor", godot_icall_NodePath_Dtor);
|
||||
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_operator_String", godot_icall_NodePath_operator_String);
|
||||
void godot_register_node_path_icalls() {
|
||||
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_as_property_path", godot_icall_NodePath_get_as_property_path);
|
||||
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_concatenated_subnames", godot_icall_NodePath_get_concatenated_subnames);
|
||||
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_name", godot_icall_NodePath_get_name);
|
||||
|
@ -91,7 +69,4 @@ void godot_register_nodepath_icalls() {
|
|||
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_subname", godot_icall_NodePath_get_subname);
|
||||
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_subname_count", godot_icall_NodePath_get_subname_count);
|
||||
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_is_absolute", godot_icall_NodePath_is_absolute);
|
||||
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_is_empty", godot_icall_NodePath_is_empty);
|
||||
}
|
||||
|
||||
#endif // MONO_GLUE_ENABLED
|
|
@ -1,5 +1,5 @@
|
|||
/*************************************************************************/
|
||||
/* rid_glue.cpp */
|
||||
/* placeholder_glue.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
|
@ -28,37 +28,24 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef MONO_GLUE_ENABLED
|
||||
#include "core/object/object.h"
|
||||
|
||||
#include "core/io/resource.h"
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/templates/rid.h"
|
||||
#include "../mono_gd/gd_mono_internals.h"
|
||||
#include "../mono_gd/gd_mono_utils.h"
|
||||
|
||||
#include "../mono_gd/gd_mono_marshal.h"
|
||||
|
||||
RID *godot_icall_RID_Ctor(Object *p_from) {
|
||||
Resource *res_from = Object::cast_to<Resource>(p_from);
|
||||
|
||||
if (res_from) {
|
||||
return memnew(RID(res_from->get_rid()));
|
||||
}
|
||||
|
||||
return memnew(RID);
|
||||
MonoObject *godot_icall_InteropUtils_unmanaged_get_managed(Object *unmanaged) {
|
||||
return GDMonoUtils::unmanaged_get_managed(unmanaged);
|
||||
}
|
||||
|
||||
void godot_icall_RID_Dtor(RID *p_ptr) {
|
||||
ERR_FAIL_NULL(p_ptr);
|
||||
memdelete(p_ptr);
|
||||
void godot_icall_InteropUtils_tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
|
||||
GDMonoInternals::tie_managed_to_unmanaged(managed, unmanaged);
|
||||
}
|
||||
|
||||
uint32_t godot_icall_RID_get_id(RID *p_ptr) {
|
||||
return p_ptr->get_id();
|
||||
void godot_register_placeholder_icalls() {
|
||||
GDMonoUtils::add_internal_call(
|
||||
"Godot.NativeInterop.InteropUtils::internal_unmanaged_get_managed",
|
||||
godot_icall_InteropUtils_unmanaged_get_managed);
|
||||
GDMonoUtils::add_internal_call(
|
||||
"Godot.NativeInterop.InteropUtils::internal_tie_managed_to_unmanaged",
|
||||
godot_icall_InteropUtils_tie_managed_to_unmanaged);
|
||||
}
|
||||
|
||||
void godot_register_rid_icalls() {
|
||||
GDMonoUtils::add_internal_call("Godot.RID::godot_icall_RID_Ctor", godot_icall_RID_Ctor);
|
||||
GDMonoUtils::add_internal_call("Godot.RID::godot_icall_RID_Dtor", godot_icall_RID_Dtor);
|
||||
GDMonoUtils::add_internal_call("Godot.RID::godot_icall_RID_get_id", godot_icall_RID_get_id);
|
||||
}
|
||||
|
||||
#endif // MONO_GLUE_ENABLED
|
649
modules/mono/glue/runtime_interop.cpp
Normal file
649
modules/mono/glue/runtime_interop.cpp
Normal file
|
@ -0,0 +1,649 @@
|
|||
/*************************************************************************/
|
||||
/* runtime_interop.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#include "core/config/engine.h"
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/object/method_bind.h"
|
||||
#include "core/string/string_name.h"
|
||||
|
||||
#include <gdnative/gdnative.h>
|
||||
|
||||
#include "modules/mono/managed_callable.h"
|
||||
#include "modules/mono/signal_awaiter_utils.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define MAYBE_UNUSED [[maybe_unused]]
|
||||
#else
|
||||
#define MAYBE_UNUSED
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define GD_PINVOKE_EXPORT MAYBE_UNUSED __attribute__((visibility("default")))
|
||||
#elif defined(_WIN32)
|
||||
#define GD_PINVOKE_EXPORT MAYBE_UNUSED __declspec(dllexport)
|
||||
#else
|
||||
#define GD_PINVOKE_EXPORT MAYBE_UNUSED
|
||||
#endif
|
||||
|
||||
typedef Object *(*godotsharp_class_creation_func)();
|
||||
|
||||
GD_PINVOKE_EXPORT MethodBind *godotsharp_method_bind_get_method(const StringName *p_classname, const char16_t *p_methodname) {
|
||||
return ClassDB::get_method(*p_classname, StringName(String::utf16(p_methodname)));
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godotsharp_class_creation_func godotsharp_get_class_constructor(const StringName *p_classname) {
|
||||
ClassDB::ClassInfo *class_info = ClassDB::classes.getptr(*p_classname);
|
||||
if (class_info) {
|
||||
return class_info->creation_func;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT Object *godotsharp_invoke_class_constructor(godotsharp_class_creation_func p_creation_func) {
|
||||
return p_creation_func();
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT Object *godotsharp_engine_get_singleton(const String *p_name) {
|
||||
return Engine::get_singleton()->get_singleton_object(*p_name);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_ref_destroy(Ref<RefCounted> *p_instance) {
|
||||
p_instance->~Ref();
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_string_name_new_from_string(StringName *r_dest, const String *p_name) {
|
||||
memnew_placement(r_dest, StringName(*p_name));
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_node_path_new_from_string(NodePath *r_dest, const String *p_name) {
|
||||
memnew_placement(r_dest, NodePath(*p_name));
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_string_name_as_string(String *r_dest, const StringName *p_name) {
|
||||
memnew_placement(r_dest, String(p_name->operator String()));
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_node_path_as_string(String *r_dest, const NodePath *p_np) {
|
||||
memnew_placement(r_dest, String(p_np->operator String()));
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_packed_byte_array godotsharp_packed_byte_array_new_mem_copy(const uint8_t *p_src, int32_t p_length) {
|
||||
godot_packed_byte_array ret;
|
||||
memnew_placement(&ret, PackedByteArray);
|
||||
PackedByteArray *array = reinterpret_cast<PackedByteArray *>(&ret);
|
||||
array->resize(p_length);
|
||||
uint8_t *dst = array->ptrw();
|
||||
memcpy(dst, p_src, p_length * sizeof(uint8_t));
|
||||
return ret;
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_packed_int32_array godotsharp_packed_int32_array_new_mem_copy(const int32_t *p_src, int32_t p_length) {
|
||||
godot_packed_int32_array ret;
|
||||
memnew_placement(&ret, PackedInt32Array);
|
||||
PackedInt32Array *array = reinterpret_cast<PackedInt32Array *>(&ret);
|
||||
array->resize(p_length);
|
||||
int32_t *dst = array->ptrw();
|
||||
memcpy(dst, p_src, p_length * sizeof(int32_t));
|
||||
return ret;
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_packed_int64_array godotsharp_packed_int64_array_new_mem_copy(const int64_t *p_src, int32_t p_length) {
|
||||
godot_packed_int64_array ret;
|
||||
memnew_placement(&ret, PackedInt64Array);
|
||||
PackedInt64Array *array = reinterpret_cast<PackedInt64Array *>(&ret);
|
||||
array->resize(p_length);
|
||||
int64_t *dst = array->ptrw();
|
||||
memcpy(dst, p_src, p_length * sizeof(int64_t));
|
||||
return ret;
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_packed_float32_array godotsharp_packed_float32_array_new_mem_copy(const float *p_src, int32_t p_length) {
|
||||
godot_packed_float32_array ret;
|
||||
memnew_placement(&ret, PackedFloat32Array);
|
||||
PackedFloat32Array *array = reinterpret_cast<PackedFloat32Array *>(&ret);
|
||||
array->resize(p_length);
|
||||
float *dst = array->ptrw();
|
||||
memcpy(dst, p_src, p_length * sizeof(float));
|
||||
return ret;
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_packed_float64_array godotsharp_packed_float64_array_new_mem_copy(const double *p_src, int32_t p_length) {
|
||||
godot_packed_float64_array ret;
|
||||
memnew_placement(&ret, PackedFloat64Array);
|
||||
PackedFloat64Array *array = reinterpret_cast<PackedFloat64Array *>(&ret);
|
||||
array->resize(p_length);
|
||||
double *dst = array->ptrw();
|
||||
memcpy(dst, p_src, p_length * sizeof(double));
|
||||
return ret;
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_packed_vector2_array godotsharp_packed_vector2_array_new_mem_copy(const Vector2 *p_src, int32_t p_length) {
|
||||
godot_packed_vector2_array ret;
|
||||
memnew_placement(&ret, PackedVector2Array);
|
||||
PackedVector2Array *array = reinterpret_cast<PackedVector2Array *>(&ret);
|
||||
array->resize(p_length);
|
||||
Vector2 *dst = array->ptrw();
|
||||
memcpy(dst, p_src, p_length * sizeof(Vector2));
|
||||
return ret;
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_packed_vector3_array godotsharp_packed_vector3_array_new_mem_copy(const Vector3 *p_src, int32_t p_length) {
|
||||
godot_packed_vector3_array ret;
|
||||
memnew_placement(&ret, PackedVector3Array);
|
||||
PackedVector3Array *array = reinterpret_cast<PackedVector3Array *>(&ret);
|
||||
array->resize(p_length);
|
||||
Vector3 *dst = array->ptrw();
|
||||
memcpy(dst, p_src, p_length * sizeof(Vector3));
|
||||
return ret;
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_packed_color_array godotsharp_packed_color_array_new_mem_copy(const Color *p_src, int32_t p_length) {
|
||||
godot_packed_color_array ret;
|
||||
memnew_placement(&ret, PackedColorArray);
|
||||
PackedColorArray *array = reinterpret_cast<PackedColorArray *>(&ret);
|
||||
array->resize(p_length);
|
||||
Color *dst = array->ptrw();
|
||||
memcpy(dst, p_src, p_length * sizeof(Color));
|
||||
return ret;
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_packed_string_array_add(PackedStringArray *r_dest, const String *p_element) {
|
||||
r_dest->append(*p_element);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_callable_new_with_delegate(void *p_delegate_handle, Callable *r_callable) {
|
||||
// TODO: Use pooling for ManagedCallable instances.
|
||||
CallableCustom *managed_callable = memnew(ManagedCallable(p_delegate_handle));
|
||||
*r_callable = Callable(managed_callable);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT bool godotsharp_callable_get_data_for_marshalling(const Callable *p_callable,
|
||||
void **r_delegate_handle, Object **r_object, StringName *r_name) {
|
||||
if (p_callable->is_custom()) {
|
||||
CallableCustom *custom = p_callable->get_custom();
|
||||
CallableCustom::CompareEqualFunc compare_equal_func = custom->get_compare_equal_func();
|
||||
|
||||
if (compare_equal_func == ManagedCallable::compare_equal_func_ptr) {
|
||||
ManagedCallable *managed_callable = static_cast<ManagedCallable *>(custom);
|
||||
*r_delegate_handle = managed_callable->get_delegate();
|
||||
*r_object = nullptr;
|
||||
*r_name = StringName();
|
||||
return true;
|
||||
} else if (compare_equal_func == SignalAwaiterCallable::compare_equal_func_ptr) {
|
||||
SignalAwaiterCallable *signal_awaiter_callable = static_cast<SignalAwaiterCallable *>(custom);
|
||||
*r_delegate_handle = nullptr;
|
||||
*r_object = ObjectDB::get_instance(signal_awaiter_callable->get_object());
|
||||
*r_name = signal_awaiter_callable->get_signal();
|
||||
return true;
|
||||
} else if (compare_equal_func == EventSignalCallable::compare_equal_func_ptr) {
|
||||
EventSignalCallable *event_signal_callable = static_cast<EventSignalCallable *>(custom);
|
||||
*r_delegate_handle = nullptr;
|
||||
*r_object = ObjectDB::get_instance(event_signal_callable->get_object());
|
||||
*r_name = event_signal_callable->get_signal();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Some other CallableCustom. We only support ManagedCallable.
|
||||
*r_delegate_handle = nullptr;
|
||||
*r_object = nullptr;
|
||||
*r_name = StringName();
|
||||
return false;
|
||||
} else {
|
||||
*r_delegate_handle = nullptr;
|
||||
*r_object = ObjectDB::get_instance(p_callable->get_object_id());
|
||||
*r_name = p_callable->get_method();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// GDNative functions
|
||||
|
||||
// gdnative.h
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_method_bind_ptrcall(godot_method_bind *p_method_bind, godot_object *p_instance, const void **p_args, void *p_ret) {
|
||||
godot_method_bind_ptrcall(p_method_bind, p_instance, p_args, p_ret);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_variant godotsharp_method_bind_call(godot_method_bind *p_method_bind, godot_object *p_instance, const godot_variant **p_args, const int p_arg_count, godot_variant_call_error *p_call_error) {
|
||||
return godot_method_bind_call(p_method_bind, p_instance, p_args, p_arg_count, p_call_error);
|
||||
}
|
||||
|
||||
// variant.h
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_variant_new_string_name(godot_variant *r_dest, const godot_string_name *p_s) {
|
||||
godot_variant_new_string_name(r_dest, p_s);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_variant_new_node_path(godot_variant *r_dest, const godot_node_path *p_np) {
|
||||
godot_variant_new_node_path(r_dest, p_np);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_variant_new_object(godot_variant *r_dest, const godot_object *p_obj) {
|
||||
godot_variant_new_object(r_dest, p_obj);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_variant_new_transform2d(godot_variant *r_dest, const godot_transform2d *p_t2d) {
|
||||
godot_variant_new_transform2d(r_dest, p_t2d);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_variant_new_basis(godot_variant *r_dest, const godot_basis *p_basis) {
|
||||
godot_variant_new_basis(r_dest, p_basis);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_variant_new_transform3d(godot_variant *r_dest, const godot_transform3d *p_trans) {
|
||||
godot_variant_new_transform3d(r_dest, p_trans);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_variant_new_aabb(godot_variant *r_dest, const godot_aabb *p_aabb) {
|
||||
godot_variant_new_aabb(r_dest, p_aabb);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_variant_new_dictionary(godot_variant *r_dest, const godot_dictionary *p_dict) {
|
||||
godot_variant_new_dictionary(r_dest, p_dict);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_variant_new_array(godot_variant *r_dest, const godot_array *p_arr) {
|
||||
godot_variant_new_array(r_dest, p_arr);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_variant_new_packed_byte_array(godot_variant *r_dest, const godot_packed_byte_array *p_pba) {
|
||||
godot_variant_new_packed_byte_array(r_dest, p_pba);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_variant_new_packed_int32_array(godot_variant *r_dest, const godot_packed_int32_array *p_pia) {
|
||||
godot_variant_new_packed_int32_array(r_dest, p_pia);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_variant_new_packed_int64_array(godot_variant *r_dest, const godot_packed_int64_array *p_pia) {
|
||||
godot_variant_new_packed_int64_array(r_dest, p_pia);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_variant_new_packed_float32_array(godot_variant *r_dest, const godot_packed_float32_array *p_pra) {
|
||||
godot_variant_new_packed_float32_array(r_dest, p_pra);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_variant_new_packed_float64_array(godot_variant *r_dest, const godot_packed_float64_array *p_pra) {
|
||||
godot_variant_new_packed_float64_array(r_dest, p_pra);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_variant_new_packed_string_array(godot_variant *r_dest, const godot_packed_string_array *p_psa) {
|
||||
godot_variant_new_packed_string_array(r_dest, p_psa);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_variant_new_packed_vector2_array(godot_variant *r_dest, const godot_packed_vector2_array *p_pv2a) {
|
||||
godot_variant_new_packed_vector2_array(r_dest, p_pv2a);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_variant_new_packed_vector3_array(godot_variant *r_dest, const godot_packed_vector3_array *p_pv3a) {
|
||||
godot_variant_new_packed_vector3_array(r_dest, p_pv3a);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_variant_new_packed_color_array(godot_variant *r_dest, const godot_packed_color_array *p_pca) {
|
||||
godot_variant_new_packed_color_array(r_dest, p_pca);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_bool godotsharp_variant_as_bool(const godot_variant *p_self) {
|
||||
return godot_variant_as_bool(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_int godotsharp_variant_as_int(const godot_variant *p_self) {
|
||||
return godot_variant_as_int(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_float godotsharp_variant_as_float(const godot_variant *p_self) {
|
||||
return godot_variant_as_float(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_string godotsharp_variant_as_string(const godot_variant *p_self) {
|
||||
return godot_variant_as_string(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_vector2 godotsharp_variant_as_vector2(const godot_variant *p_self) {
|
||||
return godot_variant_as_vector2(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_vector2i godotsharp_variant_as_vector2i(const godot_variant *p_self) {
|
||||
return godot_variant_as_vector2i(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_rect2 godotsharp_variant_as_rect2(const godot_variant *p_self) {
|
||||
return godot_variant_as_rect2(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_rect2i godotsharp_variant_as_rect2i(const godot_variant *p_self) {
|
||||
return godot_variant_as_rect2i(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_vector3 godotsharp_variant_as_vector3(const godot_variant *p_self) {
|
||||
return godot_variant_as_vector3(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_vector3i godotsharp_variant_as_vector3i(const godot_variant *p_self) {
|
||||
return godot_variant_as_vector3i(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_transform2d godotsharp_variant_as_transform2d(const godot_variant *p_self) {
|
||||
return godot_variant_as_transform2d(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_plane godotsharp_variant_as_plane(const godot_variant *p_self) {
|
||||
return godot_variant_as_plane(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_quaternion godotsharp_variant_as_quaternion(const godot_variant *p_self) {
|
||||
return godot_variant_as_quaternion(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_aabb godotsharp_variant_as_aabb(const godot_variant *p_self) {
|
||||
return godot_variant_as_aabb(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_basis godotsharp_variant_as_basis(const godot_variant *p_self) {
|
||||
return godot_variant_as_basis(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_transform3d godotsharp_variant_as_transform3d(const godot_variant *p_self) {
|
||||
return godot_variant_as_transform3d(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_color godotsharp_variant_as_color(const godot_variant *p_self) {
|
||||
return godot_variant_as_color(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_string_name godotsharp_variant_as_string_name(const godot_variant *p_self) {
|
||||
return godot_variant_as_string_name(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_node_path godotsharp_variant_as_node_path(const godot_variant *p_self) {
|
||||
return godot_variant_as_node_path(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_rid godotsharp_variant_as_rid(const godot_variant *p_self) {
|
||||
return godot_variant_as_rid(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_callable godotsharp_variant_as_callable(const godot_variant *p_self) {
|
||||
return godot_variant_as_callable(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_signal godotsharp_variant_as_signal(const godot_variant *p_self) {
|
||||
return godot_variant_as_signal(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_dictionary godotsharp_variant_as_dictionary(const godot_variant *p_self) {
|
||||
return godot_variant_as_dictionary(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_array godotsharp_variant_as_array(const godot_variant *p_self) {
|
||||
return godot_variant_as_array(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_packed_byte_array godotsharp_variant_as_packed_byte_array(const godot_variant *p_self) {
|
||||
return godot_variant_as_packed_byte_array(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_packed_int32_array godotsharp_variant_as_packed_int32_array(const godot_variant *p_self) {
|
||||
return godot_variant_as_packed_int32_array(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_packed_int64_array godotsharp_variant_as_packed_int64_array(const godot_variant *p_self) {
|
||||
return godot_variant_as_packed_int64_array(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_packed_float32_array godotsharp_variant_as_packed_float32_array(const godot_variant *p_self) {
|
||||
return godot_variant_as_packed_float32_array(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_packed_float64_array godotsharp_variant_as_packed_float64_array(const godot_variant *p_self) {
|
||||
return godot_variant_as_packed_float64_array(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_packed_string_array godotsharp_variant_as_packed_string_array(const godot_variant *p_self) {
|
||||
return godot_variant_as_packed_string_array(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_packed_vector2_array godotsharp_variant_as_packed_vector2_array(const godot_variant *p_self) {
|
||||
return godot_variant_as_packed_vector2_array(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_packed_vector3_array godotsharp_variant_as_packed_vector3_array(const godot_variant *p_self) {
|
||||
return godot_variant_as_packed_vector3_array(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT godot_packed_color_array godotsharp_variant_as_packed_color_array(const godot_variant *p_self) {
|
||||
return godot_variant_as_packed_color_array(p_self);
|
||||
}
|
||||
|
||||
// string.h
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_string_new_with_utf16_chars(godot_string *r_dest, const char16_t *p_contents) {
|
||||
godot_string_new_with_utf16_chars(r_dest, p_contents);
|
||||
}
|
||||
|
||||
// string_name.h
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_string_name_new_copy(godot_string_name *r_dest, const godot_string_name *p_src) {
|
||||
godot_string_name_new_copy(r_dest, p_src);
|
||||
}
|
||||
|
||||
// node_path.h
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_node_path_new_copy(godot_node_path *r_dest, const godot_node_path *p_src) {
|
||||
godot_node_path_new_copy(r_dest, p_src);
|
||||
}
|
||||
|
||||
// array.h
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_array_new_copy(godot_array *r_dest, const godot_array *p_src) {
|
||||
godot_array_new_copy(r_dest, p_src);
|
||||
}
|
||||
|
||||
// dictionary.h
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_dictionary_new_copy(godot_dictionary *r_dest, const godot_dictionary *p_src) {
|
||||
godot_dictionary_new_copy(r_dest, p_src);
|
||||
}
|
||||
|
||||
// destroy functions
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_packed_byte_array_destroy(godot_packed_byte_array *p_self) {
|
||||
godot_packed_byte_array_destroy(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_packed_int32_array_destroy(godot_packed_int32_array *p_self) {
|
||||
godot_packed_int32_array_destroy(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_packed_int64_array_destroy(godot_packed_int64_array *p_self) {
|
||||
godot_packed_int64_array_destroy(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_packed_float32_array_destroy(godot_packed_float32_array *p_self) {
|
||||
godot_packed_float32_array_destroy(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_packed_float64_array_destroy(godot_packed_float64_array *p_self) {
|
||||
godot_packed_float64_array_destroy(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_packed_string_array_destroy(godot_packed_string_array *p_self) {
|
||||
godot_packed_string_array_destroy(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_packed_vector2_array_destroy(godot_packed_vector2_array *p_self) {
|
||||
godot_packed_vector2_array_destroy(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_packed_vector3_array_destroy(godot_packed_vector3_array *p_self) {
|
||||
godot_packed_vector3_array_destroy(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_packed_color_array_destroy(godot_packed_color_array *p_self) {
|
||||
godot_packed_color_array_destroy(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_variant_destroy(godot_variant *p_self) {
|
||||
godot_variant_destroy(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_string_destroy(godot_string *p_self) {
|
||||
godot_string_destroy(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_string_name_destroy(godot_string_name *p_self) {
|
||||
godot_string_name_destroy(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_node_path_destroy(godot_node_path *p_self) {
|
||||
godot_node_path_destroy(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_signal_destroy(godot_signal *p_self) {
|
||||
godot_signal_destroy(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_callable_destroy(godot_callable *p_self) {
|
||||
godot_callable_destroy(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_array_destroy(godot_array *p_self) {
|
||||
godot_array_destroy(p_self);
|
||||
}
|
||||
|
||||
GD_PINVOKE_EXPORT void godotsharp_dictionary_destroy(godot_dictionary *p_self) {
|
||||
godot_dictionary_destroy(p_self);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// We need this to prevent the functions from being stripped.
|
||||
void *godotsharp_pinvoke_funcs[95] = {
|
||||
(void *)godotsharp_method_bind_get_method,
|
||||
(void *)godotsharp_get_class_constructor,
|
||||
(void *)godotsharp_invoke_class_constructor,
|
||||
(void *)godotsharp_engine_get_singleton,
|
||||
(void *)godotsharp_ref_destroy,
|
||||
(void *)godotsharp_string_name_new_from_string,
|
||||
(void *)godotsharp_node_path_new_from_string,
|
||||
(void *)godotsharp_string_name_as_string,
|
||||
(void *)godotsharp_node_path_as_string,
|
||||
(void *)godotsharp_packed_byte_array_new_mem_copy,
|
||||
(void *)godotsharp_packed_int32_array_new_mem_copy,
|
||||
(void *)godotsharp_packed_int64_array_new_mem_copy,
|
||||
(void *)godotsharp_packed_float32_array_new_mem_copy,
|
||||
(void *)godotsharp_packed_float64_array_new_mem_copy,
|
||||
(void *)godotsharp_packed_vector2_array_new_mem_copy,
|
||||
(void *)godotsharp_packed_vector3_array_new_mem_copy,
|
||||
(void *)godotsharp_packed_color_array_new_mem_copy,
|
||||
(void *)godotsharp_packed_string_array_add,
|
||||
(void *)godotsharp_callable_new_with_delegate,
|
||||
(void *)godotsharp_callable_get_data_for_marshalling,
|
||||
(void *)godotsharp_method_bind_ptrcall,
|
||||
(void *)godotsharp_method_bind_call,
|
||||
(void *)godotsharp_variant_new_string_name,
|
||||
(void *)godotsharp_variant_new_node_path,
|
||||
(void *)godotsharp_variant_new_object,
|
||||
(void *)godotsharp_variant_new_transform2d,
|
||||
(void *)godotsharp_variant_new_basis,
|
||||
(void *)godotsharp_variant_new_transform3d,
|
||||
(void *)godotsharp_variant_new_aabb,
|
||||
(void *)godotsharp_variant_new_dictionary,
|
||||
(void *)godotsharp_variant_new_array,
|
||||
(void *)godotsharp_variant_new_packed_byte_array,
|
||||
(void *)godotsharp_variant_new_packed_int32_array,
|
||||
(void *)godotsharp_variant_new_packed_int64_array,
|
||||
(void *)godotsharp_variant_new_packed_float32_array,
|
||||
(void *)godotsharp_variant_new_packed_float64_array,
|
||||
(void *)godotsharp_variant_new_packed_string_array,
|
||||
(void *)godotsharp_variant_new_packed_vector2_array,
|
||||
(void *)godotsharp_variant_new_packed_vector3_array,
|
||||
(void *)godotsharp_variant_new_packed_color_array,
|
||||
(void *)godotsharp_variant_as_bool,
|
||||
(void *)godotsharp_variant_as_int,
|
||||
(void *)godotsharp_variant_as_float,
|
||||
(void *)godotsharp_variant_as_string,
|
||||
(void *)godotsharp_variant_as_vector2,
|
||||
(void *)godotsharp_variant_as_vector2i,
|
||||
(void *)godotsharp_variant_as_rect2,
|
||||
(void *)godotsharp_variant_as_rect2i,
|
||||
(void *)godotsharp_variant_as_vector3,
|
||||
(void *)godotsharp_variant_as_vector3i,
|
||||
(void *)godotsharp_variant_as_transform2d,
|
||||
(void *)godotsharp_variant_as_plane,
|
||||
(void *)godotsharp_variant_as_quaternion,
|
||||
(void *)godotsharp_variant_as_aabb,
|
||||
(void *)godotsharp_variant_as_basis,
|
||||
(void *)godotsharp_variant_as_transform3d,
|
||||
(void *)godotsharp_variant_as_color,
|
||||
(void *)godotsharp_variant_as_string_name,
|
||||
(void *)godotsharp_variant_as_node_path,
|
||||
(void *)godotsharp_variant_as_rid,
|
||||
(void *)godotsharp_variant_as_callable,
|
||||
(void *)godotsharp_variant_as_signal,
|
||||
(void *)godotsharp_variant_as_dictionary,
|
||||
(void *)godotsharp_variant_as_array,
|
||||
(void *)godotsharp_variant_as_packed_byte_array,
|
||||
(void *)godotsharp_variant_as_packed_int32_array,
|
||||
(void *)godotsharp_variant_as_packed_int64_array,
|
||||
(void *)godotsharp_variant_as_packed_float32_array,
|
||||
(void *)godotsharp_variant_as_packed_float64_array,
|
||||
(void *)godotsharp_variant_as_packed_string_array,
|
||||
(void *)godotsharp_variant_as_packed_vector2_array,
|
||||
(void *)godotsharp_variant_as_packed_vector3_array,
|
||||
(void *)godotsharp_variant_as_packed_color_array,
|
||||
(void *)godotsharp_string_new_with_utf16_chars,
|
||||
(void *)godotsharp_string_name_new_copy,
|
||||
(void *)godotsharp_node_path_new_copy,
|
||||
(void *)godotsharp_array_new_copy,
|
||||
(void *)godotsharp_dictionary_new_copy,
|
||||
(void *)godotsharp_packed_byte_array_destroy,
|
||||
(void *)godotsharp_packed_int32_array_destroy,
|
||||
(void *)godotsharp_packed_int64_array_destroy,
|
||||
(void *)godotsharp_packed_float32_array_destroy,
|
||||
(void *)godotsharp_packed_float64_array_destroy,
|
||||
(void *)godotsharp_packed_string_array_destroy,
|
||||
(void *)godotsharp_packed_vector2_array_destroy,
|
||||
(void *)godotsharp_packed_vector3_array_destroy,
|
||||
(void *)godotsharp_packed_color_array_destroy,
|
||||
(void *)godotsharp_variant_destroy,
|
||||
(void *)godotsharp_string_destroy,
|
||||
(void *)godotsharp_string_name_destroy,
|
||||
(void *)godotsharp_node_path_destroy,
|
||||
(void *)godotsharp_signal_destroy,
|
||||
(void *)godotsharp_callable_destroy,
|
||||
(void *)godotsharp_array_destroy,
|
||||
(void *)godotsharp_dictionary_destroy
|
||||
};
|
|
@ -28,8 +28,6 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef MONO_GLUE_ENABLED
|
||||
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/string/string_name.h"
|
||||
#include "core/variant/array.h"
|
||||
|
@ -40,9 +38,10 @@
|
|||
#include "../mono_gd/gd_mono_marshal.h"
|
||||
#include "../mono_gd/gd_mono_utils.h"
|
||||
|
||||
Array *godot_icall_SceneTree_get_nodes_in_group_Generic(SceneTree *ptr, StringName *group, MonoReflectionType *refltype) {
|
||||
void godot_icall_SceneTree_get_nodes_in_group_Generic(SceneTree *ptr, StringName *group, MonoReflectionType *refltype, Array *r_dest) {
|
||||
memnew_placement(r_dest, Array);
|
||||
|
||||
List<Node *> nodes;
|
||||
Array ret;
|
||||
|
||||
// Retrieve all the nodes in the group
|
||||
ptr->get_nodes_in_group(*group, &nodes);
|
||||
|
@ -58,7 +57,7 @@ Array *godot_icall_SceneTree_get_nodes_in_group_Generic(SceneTree *ptr, StringNa
|
|||
StringName native_class_name = GDMonoUtils::get_native_godot_class_name(klass);
|
||||
for (int i = 0; i < nodes.size(); ++i) {
|
||||
if (ClassDB::is_parent_class(nodes[i]->get_class(), native_class_name)) {
|
||||
ret.push_back(nodes[i]);
|
||||
r_dest->push_back(nodes[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -69,18 +68,14 @@ Array *godot_icall_SceneTree_get_nodes_in_group_Generic(SceneTree *ptr, StringNa
|
|||
if (si != nullptr) {
|
||||
MonoObject *obj = si->get_mono_object();
|
||||
if (obj != nullptr && mono_object_get_class(obj) == mono_class) {
|
||||
ret.push_back(nodes[i]);
|
||||
r_dest->push_back(nodes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return memnew(Array(ret));
|
||||
}
|
||||
|
||||
void godot_register_scene_tree_icalls() {
|
||||
GDMonoUtils::add_internal_call("Godot.SceneTree::godot_icall_SceneTree_get_nodes_in_group_Generic", godot_icall_SceneTree_get_nodes_in_group_Generic);
|
||||
}
|
||||
|
||||
#endif // MONO_GLUE_ENABLED
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef MONO_GLUE_ENABLED
|
||||
|
||||
#include "core/string/ustring.h"
|
||||
#include "core/templates/vector.h"
|
||||
#include "core/variant/variant.h"
|
||||
|
@ -75,5 +73,3 @@ void godot_register_string_icalls() {
|
|||
GDMonoUtils::add_internal_call("Godot.StringExtensions::godot_icall_String_sha256_buffer", godot_icall_String_sha256_buffer);
|
||||
GDMonoUtils::add_internal_call("Godot.StringExtensions::godot_icall_String_sha256_text", godot_icall_String_sha256_text);
|
||||
}
|
||||
|
||||
#endif // MONO_GLUE_ENABLED
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* string_name_glue.cpp */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifdef MONO_GLUE_ENABLED
|
||||
|
||||
#include "core/string/string_name.h"
|
||||
#include "core/string/ustring.h"
|
||||
|
||||
#include "../mono_gd/gd_mono_marshal.h"
|
||||
|
||||
StringName *godot_icall_StringName_Ctor(MonoString *p_path) {
|
||||
return memnew(StringName(GDMonoMarshal::mono_string_to_godot(p_path)));
|
||||
}
|
||||
|
||||
void godot_icall_StringName_Dtor(StringName *p_ptr) {
|
||||
ERR_FAIL_NULL(p_ptr);
|
||||
memdelete(p_ptr);
|
||||
}
|
||||
|
||||
MonoString *godot_icall_StringName_operator_String(StringName *p_np) {
|
||||
return GDMonoMarshal::mono_string_from_godot(p_np->operator String());
|
||||
}
|
||||
|
||||
MonoBoolean godot_icall_StringName_is_empty(StringName *p_ptr) {
|
||||
return (MonoBoolean)(*p_ptr == StringName());
|
||||
}
|
||||
|
||||
void godot_register_string_name_icalls() {
|
||||
GDMonoUtils::add_internal_call("Godot.StringName::godot_icall_StringName_Ctor", godot_icall_StringName_Ctor);
|
||||
GDMonoUtils::add_internal_call("Godot.StringName::godot_icall_StringName_Dtor", godot_icall_StringName_Dtor);
|
||||
GDMonoUtils::add_internal_call("Godot.StringName::godot_icall_StringName_operator_String", godot_icall_StringName_operator_String);
|
||||
GDMonoUtils::add_internal_call("Godot.StringName::godot_icall_StringName_is_empty", godot_icall_StringName_is_empty);
|
||||
}
|
||||
|
||||
#endif // MONO_GLUE_ENABLED
|
|
@ -34,8 +34,8 @@
|
|||
#define BINDINGS_NAMESPACE "Godot"
|
||||
#define BINDINGS_NAMESPACE_COLLECTIONS BINDINGS_NAMESPACE ".Collections"
|
||||
#define BINDINGS_GLOBAL_SCOPE_CLASS "GD"
|
||||
#define BINDINGS_PTR_FIELD "ptr"
|
||||
#define BINDINGS_NATIVE_NAME_FIELD "nativeName"
|
||||
#define BINDINGS_PTR_FIELD "NativePtr"
|
||||
#define BINDINGS_NATIVE_NAME_FIELD "NativeName"
|
||||
#define API_SOLUTION_NAME "GodotSharp"
|
||||
#define CORE_API_ASSEMBLY_NAME "GodotSharp"
|
||||
#define EDITOR_API_ASSEMBLY_NAME "GodotSharpEditor"
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "managed_callable.h"
|
||||
|
||||
#include "csharp_script.h"
|
||||
#include "mono_gd/gd_mono_cache.h"
|
||||
#include "mono_gd/gd_mono_marshal.h"
|
||||
#include "mono_gd/gd_mono_utils.h"
|
||||
|
||||
|
@ -44,18 +45,20 @@ bool ManagedCallable::compare_equal(const CallableCustom *p_a, const CallableCus
|
|||
const ManagedCallable *a = static_cast<const ManagedCallable *>(p_a);
|
||||
const ManagedCallable *b = static_cast<const ManagedCallable *>(p_b);
|
||||
|
||||
MonoDelegate *delegate_a = (MonoDelegate *)a->delegate_handle.get_target();
|
||||
MonoDelegate *delegate_b = (MonoDelegate *)b->delegate_handle.get_target();
|
||||
|
||||
if (!delegate_a || !delegate_b) {
|
||||
if (!delegate_a && !delegate_b) {
|
||||
if (!a->delegate_handle || !b->delegate_handle) {
|
||||
if (!a->delegate_handle && !b->delegate_handle) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Call Delegate's 'Equals'
|
||||
return GDMonoUtils::mono_delegate_equal(delegate_a, delegate_b);
|
||||
MonoException *exc = nullptr;
|
||||
MonoBoolean res = CACHED_METHOD_THUNK(DelegateUtils, DelegateEquals)
|
||||
.invoke(a->delegate_handle,
|
||||
b->delegate_handle, &exc);
|
||||
UNHANDLED_EXCEPTION(exc);
|
||||
return (bool)res;
|
||||
}
|
||||
|
||||
bool ManagedCallable::compare_less(const CallableCustom *p_a, const CallableCustom *p_b) {
|
||||
|
@ -66,9 +69,7 @@ bool ManagedCallable::compare_less(const CallableCustom *p_a, const CallableCust
|
|||
}
|
||||
|
||||
uint32_t ManagedCallable::hash() const {
|
||||
// hmm
|
||||
uint32_t hash = delegate_invoke->get_name().hash();
|
||||
return hash_djb2_one_64(delegate_handle.handle, hash);
|
||||
return hash_djb2_one_64((uint64_t)delegate_handle);
|
||||
}
|
||||
|
||||
String ManagedCallable::get_as_text() const {
|
||||
|
@ -92,41 +93,34 @@ void ManagedCallable::call(const Variant **p_arguments, int p_argcount, Variant
|
|||
r_call_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; // Can't find anything better
|
||||
r_return_value = Variant();
|
||||
|
||||
#ifdef GD_MONO_HOT_RELOAD
|
||||
// Lost during hot-reload
|
||||
ERR_FAIL_NULL(delegate_invoke);
|
||||
ERR_FAIL_COND(delegate_handle.is_released());
|
||||
#endif
|
||||
|
||||
ERR_FAIL_COND(delegate_invoke->get_parameters_count() < p_argcount);
|
||||
|
||||
MonoObject *delegate = delegate_handle.get_target();
|
||||
|
||||
MonoException *exc = nullptr;
|
||||
MonoObject *ret = delegate_invoke->invoke(delegate, p_arguments, &exc);
|
||||
CACHED_METHOD_THUNK(DelegateUtils, InvokeWithVariantArgs)
|
||||
.invoke(delegate_handle, p_arguments,
|
||||
p_argcount, &r_return_value, &exc);
|
||||
|
||||
if (exc) {
|
||||
GDMonoUtils::set_pending_exception(exc);
|
||||
} else {
|
||||
r_return_value = GDMonoMarshal::mono_object_to_variant(ret);
|
||||
r_call_error.error = Callable::CallError::CALL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
void ManagedCallable::set_delegate(MonoDelegate *p_delegate) {
|
||||
delegate_handle = MonoGCHandleData::new_strong_handle((MonoObject *)p_delegate);
|
||||
MonoMethod *delegate_invoke_raw = mono_get_delegate_invoke(mono_object_get_class((MonoObject *)p_delegate));
|
||||
const StringName &delegate_invoke_name = CSharpLanguage::get_singleton()->get_string_names().delegate_invoke_method_name;
|
||||
delegate_invoke = memnew(GDMonoMethod(delegate_invoke_name, delegate_invoke_raw)); // TODO: Use pooling for this GDMonoMethod instances
|
||||
void ManagedCallable::release_delegate_handle() {
|
||||
if (delegate_handle) {
|
||||
MonoException *exc = nullptr;
|
||||
CACHED_METHOD_THUNK(DelegateUtils, FreeGCHandle).invoke(delegate_handle, &exc);
|
||||
|
||||
if (exc) {
|
||||
GDMonoUtils::debug_print_unhandled_exception(exc);
|
||||
}
|
||||
|
||||
delegate_handle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ManagedCallable::ManagedCallable(MonoDelegate *p_delegate) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
CRASH_COND(p_delegate == nullptr);
|
||||
#endif
|
||||
|
||||
set_delegate(p_delegate);
|
||||
|
||||
// Why you do this clang-format...
|
||||
/* clang-format off */
|
||||
ManagedCallable::ManagedCallable(void *p_delegate_handle) : delegate_handle(p_delegate_handle) {
|
||||
#ifdef GD_MONO_HOT_RELOAD
|
||||
{
|
||||
MutexLock lock(instances_mutex);
|
||||
|
@ -134,6 +128,7 @@ ManagedCallable::ManagedCallable(MonoDelegate *p_delegate) {
|
|||
}
|
||||
#endif
|
||||
}
|
||||
/* clang-format on */
|
||||
|
||||
ManagedCallable::~ManagedCallable() {
|
||||
#ifdef GD_MONO_HOT_RELOAD
|
||||
|
@ -144,5 +139,5 @@ ManagedCallable::~ManagedCallable() {
|
|||
}
|
||||
#endif
|
||||
|
||||
delegate_handle.release();
|
||||
release_delegate_handle();
|
||||
}
|
||||
|
|
|
@ -42,8 +42,7 @@
|
|||
|
||||
class ManagedCallable : public CallableCustom {
|
||||
friend class CSharpLanguage;
|
||||
MonoGCHandleData delegate_handle;
|
||||
GDMonoMethod *delegate_invoke;
|
||||
void *delegate_handle;
|
||||
|
||||
#ifdef GD_MONO_HOT_RELOAD
|
||||
SelfList<ManagedCallable> self_instance = this;
|
||||
|
@ -60,9 +59,7 @@ public:
|
|||
ObjectID get_object() const override;
|
||||
void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
|
||||
|
||||
_FORCE_INLINE_ MonoDelegate *get_delegate() { return (MonoDelegate *)delegate_handle.get_target(); }
|
||||
|
||||
void set_delegate(MonoDelegate *p_delegate);
|
||||
_FORCE_INLINE_ void *get_delegate() const { return delegate_handle; }
|
||||
|
||||
static bool compare_equal(const CallableCustom *p_a, const CallableCustom *p_b);
|
||||
static bool compare_less(const CallableCustom *p_a, const CallableCustom *p_b);
|
||||
|
@ -70,7 +67,9 @@ public:
|
|||
static constexpr CompareEqualFunc compare_equal_func_ptr = &ManagedCallable::compare_equal;
|
||||
static constexpr CompareEqualFunc compare_less_func_ptr = &ManagedCallable::compare_less;
|
||||
|
||||
ManagedCallable(MonoDelegate *p_delegate);
|
||||
void release_delegate_handle();
|
||||
|
||||
ManagedCallable(void *p_delegate_handle);
|
||||
~ManagedCallable();
|
||||
};
|
||||
|
||||
|
|
|
@ -410,10 +410,6 @@ void GDMono::initialize() {
|
|||
}
|
||||
|
||||
void GDMono::initialize_load_assemblies() {
|
||||
#ifndef MONO_GLUE_ENABLED
|
||||
CRASH_NOW_MSG("Mono: This binary was built with 'mono_glue=no'; cannot load assemblies.");
|
||||
#endif
|
||||
|
||||
// Load assemblies. The API and tools assemblies are required,
|
||||
// the application is aborted if these assemblies cannot be loaded.
|
||||
|
||||
|
@ -448,59 +444,34 @@ bool GDMono::_are_api_assemblies_out_of_sync() {
|
|||
return out_of_sync;
|
||||
}
|
||||
|
||||
namespace GodotSharpBindings {
|
||||
#ifdef MONO_GLUE_ENABLED
|
||||
|
||||
uint64_t get_core_api_hash();
|
||||
#ifdef TOOLS_ENABLED
|
||||
uint64_t get_editor_api_hash();
|
||||
#endif
|
||||
uint32_t get_bindings_version();
|
||||
uint32_t get_cs_glue_version();
|
||||
|
||||
void register_generated_icalls();
|
||||
|
||||
#else
|
||||
|
||||
uint64_t get_core_api_hash() {
|
||||
GD_UNREACHABLE();
|
||||
}
|
||||
#ifdef TOOLS_ENABLED
|
||||
uint64_t get_editor_api_hash() {
|
||||
GD_UNREACHABLE();
|
||||
}
|
||||
#endif
|
||||
uint32_t get_bindings_version() {
|
||||
GD_UNREACHABLE();
|
||||
}
|
||||
|
||||
uint32_t get_cs_glue_version() {
|
||||
GD_UNREACHABLE();
|
||||
}
|
||||
|
||||
void register_generated_icalls() {
|
||||
/* Fine, just do nothing */
|
||||
}
|
||||
|
||||
#endif // MONO_GLUE_ENABLED
|
||||
} // namespace GodotSharpBindings
|
||||
void godot_register_collections_icalls();
|
||||
void godot_register_gd_icalls();
|
||||
void godot_register_node_path_icalls();
|
||||
void godot_register_object_icalls();
|
||||
void godot_register_rid_icalls();
|
||||
void godot_register_string_icalls();
|
||||
void godot_register_scene_tree_icalls();
|
||||
void godot_register_placeholder_icalls();
|
||||
|
||||
void GDMono::_register_internal_calls() {
|
||||
GodotSharpBindings::register_generated_icalls();
|
||||
// Registers internal calls that were not generated.
|
||||
godot_register_collections_icalls();
|
||||
godot_register_gd_icalls();
|
||||
godot_register_node_path_icalls();
|
||||
godot_register_object_icalls();
|
||||
godot_register_string_icalls();
|
||||
godot_register_scene_tree_icalls();
|
||||
godot_register_placeholder_icalls();
|
||||
}
|
||||
|
||||
void GDMono::_init_godot_api_hashes() {
|
||||
#if defined(MONO_GLUE_ENABLED) && defined(DEBUG_METHODS_ENABLED)
|
||||
if (get_api_core_hash() != GodotSharpBindings::get_core_api_hash()) {
|
||||
ERR_PRINT("Mono: Core API hash mismatch.");
|
||||
}
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
get_api_core_hash();
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (get_api_editor_hash() != GodotSharpBindings::get_editor_api_hash()) {
|
||||
ERR_PRINT("Mono: Editor API hash mismatch.");
|
||||
}
|
||||
get_api_editor_hash();
|
||||
#endif // TOOLS_ENABLED
|
||||
#endif // MONO_GLUE_ENABLED && DEBUG_METHODS_ENABLED
|
||||
#endif // DEBUG_METHODS_ENABLED
|
||||
}
|
||||
|
||||
void GDMono::_init_exception_policy() {
|
||||
|
@ -603,16 +574,6 @@ ApiAssemblyInfo::Version ApiAssemblyInfo::Version::get_from_loaded_assembly(GDMo
|
|||
if (api_hash_field) {
|
||||
api_assembly_version.godot_api_hash = GDMonoMarshal::unbox<uint64_t>(api_hash_field->get_value(nullptr));
|
||||
}
|
||||
|
||||
GDMonoField *binds_ver_field = nativecalls_klass->get_field("bindings_version");
|
||||
if (binds_ver_field) {
|
||||
api_assembly_version.bindings_version = GDMonoMarshal::unbox<uint32_t>(binds_ver_field->get_value(nullptr));
|
||||
}
|
||||
|
||||
GDMonoField *cs_glue_ver_field = nativecalls_klass->get_field("cs_glue_version");
|
||||
if (cs_glue_ver_field) {
|
||||
api_assembly_version.cs_glue_version = GDMonoMarshal::unbox<uint32_t>(cs_glue_ver_field->get_value(nullptr));
|
||||
}
|
||||
}
|
||||
|
||||
return api_assembly_version;
|
||||
|
@ -701,12 +662,8 @@ static bool try_get_cached_api_hash_for(const String &p_api_assemblies_dir, bool
|
|||
return false;
|
||||
}
|
||||
|
||||
r_out_of_sync = GodotSharpBindings::get_bindings_version() != (uint32_t)cfg->get_value("core", "bindings_version") ||
|
||||
GodotSharpBindings::get_cs_glue_version() != (uint32_t)cfg->get_value("core", "cs_glue_version") ||
|
||||
GodotSharpBindings::get_bindings_version() != (uint32_t)cfg->get_value("editor", "bindings_version") ||
|
||||
GodotSharpBindings::get_cs_glue_version() != (uint32_t)cfg->get_value("editor", "cs_glue_version") ||
|
||||
GodotSharpBindings::get_core_api_hash() != (uint64_t)cfg->get_value("core", "api_hash") ||
|
||||
GodotSharpBindings::get_editor_api_hash() != (uint64_t)cfg->get_value("editor", "api_hash");
|
||||
r_out_of_sync = GDMono::get_singleton()->get_api_core_hash() != (uint64_t)cfg->get_value("core", "api_hash") ||
|
||||
GDMono::get_singleton()->get_api_editor_hash() != (uint64_t)cfg->get_value("editor", "api_hash");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -722,14 +679,9 @@ static void create_cached_api_hash_for(const String &p_api_assemblies_dir) {
|
|||
cfg->set_value("core", "modified_time", FileAccess::get_modified_time(core_api_assembly_path));
|
||||
cfg->set_value("editor", "modified_time", FileAccess::get_modified_time(editor_api_assembly_path));
|
||||
|
||||
cfg->set_value("core", "bindings_version", GodotSharpBindings::get_bindings_version());
|
||||
cfg->set_value("core", "cs_glue_version", GodotSharpBindings::get_cs_glue_version());
|
||||
cfg->set_value("editor", "bindings_version", GodotSharpBindings::get_bindings_version());
|
||||
cfg->set_value("editor", "cs_glue_version", GodotSharpBindings::get_cs_glue_version());
|
||||
|
||||
// This assumes the prebuilt api assemblies we copied to the project are not out of sync
|
||||
cfg->set_value("core", "api_hash", GodotSharpBindings::get_core_api_hash());
|
||||
cfg->set_value("editor", "api_hash", GodotSharpBindings::get_editor_api_hash());
|
||||
cfg->set_value("core", "api_hash", GDMono::get_singleton()->get_api_core_hash());
|
||||
cfg->set_value("editor", "api_hash", GDMono::get_singleton()->get_api_editor_hash());
|
||||
|
||||
Error err = cfg->save(cached_api_hash_path);
|
||||
ERR_FAIL_COND(err != OK);
|
||||
|
@ -771,7 +723,7 @@ String GDMono::update_api_assemblies_from_prebuilt(const String &p_config, const
|
|||
bool api_assemblies_out_of_sync = false;
|
||||
|
||||
if (p_core_api_out_of_sync && p_editor_api_out_of_sync) {
|
||||
api_assemblies_out_of_sync = p_core_api_out_of_sync || p_editor_api_out_of_sync;
|
||||
api_assemblies_out_of_sync = *p_core_api_out_of_sync || *p_editor_api_out_of_sync;
|
||||
} else if (FileAccess::exists(core_assembly_path) && FileAccess::exists(editor_assembly_path)) {
|
||||
// Determine if they're out of sync
|
||||
if (!try_get_cached_api_hash_for(dst_assemblies_dir, api_assemblies_out_of_sync)) {
|
||||
|
@ -831,14 +783,16 @@ bool GDMono::_load_core_api_assembly(LoadedApiAssembly &r_loaded_api_assembly, c
|
|||
bool success = load_assembly(CORE_API_ASSEMBLY_NAME, &r_loaded_api_assembly.assembly, p_refonly);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
if (success) {
|
||||
ApiAssemblyInfo::Version api_assembly_ver = ApiAssemblyInfo::Version::get_from_loaded_assembly(r_loaded_api_assembly.assembly, ApiAssemblyInfo::API_CORE);
|
||||
r_loaded_api_assembly.out_of_sync = GodotSharpBindings::get_core_api_hash() != api_assembly_ver.godot_api_hash ||
|
||||
GodotSharpBindings::get_bindings_version() != api_assembly_ver.bindings_version ||
|
||||
GodotSharpBindings::get_cs_glue_version() != api_assembly_ver.cs_glue_version;
|
||||
r_loaded_api_assembly.out_of_sync = get_api_core_hash() != api_assembly_ver.godot_api_hash;
|
||||
} else {
|
||||
r_loaded_api_assembly.out_of_sync = false;
|
||||
}
|
||||
#else
|
||||
r_loaded_api_assembly.out_of_sync = false;
|
||||
#endif
|
||||
|
||||
return success;
|
||||
}
|
||||
|
@ -861,14 +815,16 @@ bool GDMono::_load_editor_api_assembly(LoadedApiAssembly &r_loaded_api_assembly,
|
|||
bool success = FileAccess::exists(assembly_path) &&
|
||||
load_assembly_from(EDITOR_API_ASSEMBLY_NAME, assembly_path, &r_loaded_api_assembly.assembly, p_refonly);
|
||||
|
||||
#ifdef DEBUG_METHODS_ENABLED
|
||||
if (success) {
|
||||
ApiAssemblyInfo::Version api_assembly_ver = ApiAssemblyInfo::Version::get_from_loaded_assembly(r_loaded_api_assembly.assembly, ApiAssemblyInfo::API_EDITOR);
|
||||
r_loaded_api_assembly.out_of_sync = GodotSharpBindings::get_editor_api_hash() != api_assembly_ver.godot_api_hash ||
|
||||
GodotSharpBindings::get_bindings_version() != api_assembly_ver.bindings_version ||
|
||||
GodotSharpBindings::get_cs_glue_version() != api_assembly_ver.cs_glue_version;
|
||||
r_loaded_api_assembly.out_of_sync = get_api_editor_hash() != api_assembly_ver.godot_api_hash;
|
||||
} else {
|
||||
r_loaded_api_assembly.out_of_sync = false;
|
||||
}
|
||||
#else
|
||||
r_loaded_api_assembly.out_of_sync = false;
|
||||
#endif
|
||||
|
||||
return success;
|
||||
}
|
||||
|
@ -1098,13 +1054,13 @@ Error GDMono::_unload_scripts_domain() {
|
|||
Error GDMono::reload_scripts_domain() {
|
||||
ERR_FAIL_COND_V(!runtime_initialized, ERR_BUG);
|
||||
|
||||
CSharpLanguage::get_singleton()->_on_scripts_domain_about_to_unload();
|
||||
|
||||
if (scripts_domain) {
|
||||
Error domain_unload_err = _unload_scripts_domain();
|
||||
ERR_FAIL_COND_V_MSG(domain_unload_err != OK, domain_unload_err, "Mono: Failed to unload scripts domain.");
|
||||
}
|
||||
|
||||
CSharpLanguage::get_singleton()->_on_scripts_domain_unloaded();
|
||||
|
||||
Error domain_load_err = _load_scripts_domain();
|
||||
ERR_FAIL_COND_V_MSG(domain_load_err != OK, domain_load_err, "Mono: Failed to load scripts domain.");
|
||||
|
||||
|
|
|
@ -49,23 +49,15 @@ enum Type {
|
|||
|
||||
struct Version {
|
||||
uint64_t godot_api_hash = 0;
|
||||
uint32_t bindings_version = 0;
|
||||
uint32_t cs_glue_version = 0;
|
||||
|
||||
bool operator==(const Version &p_other) const {
|
||||
return godot_api_hash == p_other.godot_api_hash &&
|
||||
bindings_version == p_other.bindings_version &&
|
||||
cs_glue_version == p_other.cs_glue_version;
|
||||
return godot_api_hash == p_other.godot_api_hash;
|
||||
}
|
||||
|
||||
Version() {}
|
||||
|
||||
Version(uint64_t p_godot_api_hash,
|
||||
uint32_t p_bindings_version,
|
||||
uint32_t p_cs_glue_version) :
|
||||
godot_api_hash(p_godot_api_hash),
|
||||
bindings_version(p_bindings_version),
|
||||
cs_glue_version(p_cs_glue_version) {
|
||||
Version(uint64_t p_godot_api_hash) :
|
||||
godot_api_hash(p_godot_api_hash) {
|
||||
}
|
||||
|
||||
static Version get_from_loaded_assembly(GDMonoAssembly *p_api_assembly, Type p_api_type);
|
||||
|
|
|
@ -48,11 +48,8 @@ CachedData cached_data;
|
|||
}
|
||||
|
||||
#define CACHE_CLASS_AND_CHECK(m_class, m_val) CACHE_AND_CHECK(cached_data.class_##m_class, m_val)
|
||||
#define CACHE_NS_CLASS_AND_CHECK(m_ns, m_class, m_val) CACHE_AND_CHECK(cached_data.class_##m_ns##_##m_class, m_val)
|
||||
#define CACHE_RAW_MONO_CLASS_AND_CHECK(m_class, m_val) CACHE_AND_CHECK(cached_data.rawclass_##m_class, m_val)
|
||||
#define CACHE_FIELD_AND_CHECK(m_class, m_field, m_val) CACHE_AND_CHECK(cached_data.field_##m_class##_##m_field, m_val)
|
||||
#define CACHE_METHOD_AND_CHECK(m_class, m_method, m_val) CACHE_AND_CHECK(cached_data.method_##m_class##_##m_method, m_val)
|
||||
#define CACHE_PROPERTY_AND_CHECK(m_class, m_property, m_val) CACHE_AND_CHECK(cached_data.property_##m_class##_##m_property, m_val)
|
||||
|
||||
#define CACHE_METHOD_THUNK_AND_CHECK_IMPL(m_var, m_val) \
|
||||
{ \
|
||||
|
@ -68,23 +65,7 @@ void CachedData::clear_corlib_cache() {
|
|||
corlib_cache_updated = false;
|
||||
|
||||
class_MonoObject = nullptr;
|
||||
class_bool = nullptr;
|
||||
class_int8_t = nullptr;
|
||||
class_int16_t = nullptr;
|
||||
class_int32_t = nullptr;
|
||||
class_int64_t = nullptr;
|
||||
class_uint8_t = nullptr;
|
||||
class_uint16_t = nullptr;
|
||||
class_uint32_t = nullptr;
|
||||
class_uint64_t = nullptr;
|
||||
class_float = nullptr;
|
||||
class_double = nullptr;
|
||||
class_String = nullptr;
|
||||
class_IntPtr = nullptr;
|
||||
|
||||
class_System_Collections_IEnumerable = nullptr;
|
||||
class_System_Collections_ICollection = nullptr;
|
||||
class_System_Collections_IDictionary = nullptr;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
class_System_Diagnostics_StackTrace = nullptr;
|
||||
|
@ -99,35 +80,11 @@ void CachedData::clear_corlib_cache() {
|
|||
void CachedData::clear_godot_api_cache() {
|
||||
godot_api_cache_updated = false;
|
||||
|
||||
rawclass_Dictionary = nullptr;
|
||||
|
||||
class_Vector2 = nullptr;
|
||||
class_Vector2i = nullptr;
|
||||
class_Rect2 = nullptr;
|
||||
class_Rect2i = nullptr;
|
||||
class_Transform2D = nullptr;
|
||||
class_Vector3 = nullptr;
|
||||
class_Vector3i = nullptr;
|
||||
class_Basis = nullptr;
|
||||
class_Quaternion = nullptr;
|
||||
class_Transform3D = nullptr;
|
||||
class_AABB = nullptr;
|
||||
class_Color = nullptr;
|
||||
class_Plane = nullptr;
|
||||
class_StringName = nullptr;
|
||||
class_NodePath = nullptr;
|
||||
class_RID = nullptr;
|
||||
class_GodotObject = nullptr;
|
||||
class_GodotResource = nullptr;
|
||||
class_Node = nullptr;
|
||||
class_Control = nullptr;
|
||||
class_Node3D = nullptr;
|
||||
class_WeakRef = nullptr;
|
||||
class_Callable = nullptr;
|
||||
class_SignalInfo = nullptr;
|
||||
class_Array = nullptr;
|
||||
class_Dictionary = nullptr;
|
||||
class_MarshalUtils = nullptr;
|
||||
class_ISerializationListener = nullptr;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
@ -152,65 +109,37 @@ void CachedData::clear_godot_api_cache() {
|
|||
field_AssemblyHasScriptsAttribute_scriptTypes = nullptr;
|
||||
|
||||
field_GodotObject_ptr = nullptr;
|
||||
field_StringName_ptr = nullptr;
|
||||
field_NodePath_ptr = nullptr;
|
||||
field_Image_ptr = nullptr;
|
||||
field_RID_ptr = nullptr;
|
||||
|
||||
methodthunk_GodotObject_Dispose.nullify();
|
||||
methodthunk_Array_GetPtr.nullify();
|
||||
methodthunk_Dictionary_GetPtr.nullify();
|
||||
methodthunk_SignalAwaiter_SignalCallback.nullify();
|
||||
methodthunk_GodotTaskScheduler_Activate.nullify();
|
||||
|
||||
methodthunk_Delegate_Equals.nullify();
|
||||
|
||||
methodthunk_DelegateUtils_TrySerializeDelegateWithGCHandle.nullify();
|
||||
methodthunk_DelegateUtils_TryDeserializeDelegateWithGCHandle.nullify();
|
||||
methodthunk_DelegateUtils_TrySerializeDelegate.nullify();
|
||||
methodthunk_DelegateUtils_TryDeserializeDelegate.nullify();
|
||||
methodthunk_DelegateUtils_InvokeWithVariantArgs.nullify();
|
||||
methodthunk_DelegateUtils_DelegateEquals.nullify();
|
||||
methodthunk_DelegateUtils_FreeGCHandle.nullify();
|
||||
|
||||
// Start of MarshalUtils methods
|
||||
methodthunk_Marshaling_managed_to_variant_type.nullify();
|
||||
methodthunk_Marshaling_try_get_array_element_type.nullify();
|
||||
methodthunk_Marshaling_variant_to_mono_object_of_type.nullify();
|
||||
methodthunk_Marshaling_variant_to_mono_object.nullify();
|
||||
methodthunk_Marshaling_mono_object_to_variant_out.nullify();
|
||||
|
||||
methodthunk_MarshalUtils_TypeIsGenericArray.nullify();
|
||||
methodthunk_MarshalUtils_TypeIsGenericDictionary.nullify();
|
||||
methodthunk_MarshalUtils_TypeIsSystemGenericList.nullify();
|
||||
methodthunk_MarshalUtils_TypeIsSystemGenericDictionary.nullify();
|
||||
methodthunk_MarshalUtils_TypeIsGenericIEnumerable.nullify();
|
||||
methodthunk_MarshalUtils_TypeIsGenericICollection.nullify();
|
||||
methodthunk_MarshalUtils_TypeIsGenericIDictionary.nullify();
|
||||
|
||||
methodthunk_MarshalUtils_ArrayGetElementType.nullify();
|
||||
methodthunk_MarshalUtils_DictionaryGetKeyValueTypes.nullify();
|
||||
|
||||
methodthunk_MarshalUtils_MakeGenericArrayType.nullify();
|
||||
methodthunk_MarshalUtils_MakeGenericDictionaryType.nullify();
|
||||
|
||||
// End of MarshalUtils methods
|
||||
methodthunk_Marshaling_SetFieldValue.nullify();
|
||||
|
||||
task_scheduler_handle = Ref<MonoGCHandleRef>();
|
||||
}
|
||||
|
||||
#define GODOT_API_CLASS(m_class) (GDMono::get_singleton()->get_core_api_assembly()->get_class(BINDINGS_NAMESPACE, #m_class))
|
||||
#define GODOT_API_NS_CLASS(m_ns, m_class) (GDMono::get_singleton()->get_core_api_assembly()->get_class(m_ns, #m_class))
|
||||
|
||||
void update_corlib_cache() {
|
||||
CACHE_CLASS_AND_CHECK(MonoObject, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_object_class()));
|
||||
CACHE_CLASS_AND_CHECK(bool, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_boolean_class()));
|
||||
CACHE_CLASS_AND_CHECK(int8_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_sbyte_class()));
|
||||
CACHE_CLASS_AND_CHECK(int16_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_int16_class()));
|
||||
CACHE_CLASS_AND_CHECK(int32_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_int32_class()));
|
||||
CACHE_CLASS_AND_CHECK(int64_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_int64_class()));
|
||||
CACHE_CLASS_AND_CHECK(uint8_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_byte_class()));
|
||||
CACHE_CLASS_AND_CHECK(uint16_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_uint16_class()));
|
||||
CACHE_CLASS_AND_CHECK(uint32_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_uint32_class()));
|
||||
CACHE_CLASS_AND_CHECK(uint64_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_uint64_class()));
|
||||
CACHE_CLASS_AND_CHECK(float, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_single_class()));
|
||||
CACHE_CLASS_AND_CHECK(double, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_double_class()));
|
||||
CACHE_CLASS_AND_CHECK(String, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_string_class()));
|
||||
CACHE_CLASS_AND_CHECK(IntPtr, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_intptr_class()));
|
||||
|
||||
CACHE_CLASS_AND_CHECK(System_Collections_IEnumerable, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Collections", "IEnumerable"));
|
||||
CACHE_CLASS_AND_CHECK(System_Collections_ICollection, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Collections", "ICollection"));
|
||||
CACHE_CLASS_AND_CHECK(System_Collections_IDictionary, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Collections", "IDictionary"));
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
CACHE_CLASS_AND_CHECK(System_Diagnostics_StackTrace, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Diagnostics", "StackTrace"));
|
||||
|
@ -227,33 +156,11 @@ void update_corlib_cache() {
|
|||
}
|
||||
|
||||
void update_godot_api_cache() {
|
||||
CACHE_CLASS_AND_CHECK(Vector2, GODOT_API_CLASS(Vector2));
|
||||
CACHE_CLASS_AND_CHECK(Vector2i, GODOT_API_CLASS(Vector2i));
|
||||
CACHE_CLASS_AND_CHECK(Rect2, GODOT_API_CLASS(Rect2));
|
||||
CACHE_CLASS_AND_CHECK(Rect2i, GODOT_API_CLASS(Rect2i));
|
||||
CACHE_CLASS_AND_CHECK(Transform2D, GODOT_API_CLASS(Transform2D));
|
||||
CACHE_CLASS_AND_CHECK(Vector3, GODOT_API_CLASS(Vector3));
|
||||
CACHE_CLASS_AND_CHECK(Vector3i, GODOT_API_CLASS(Vector3i));
|
||||
CACHE_CLASS_AND_CHECK(Basis, GODOT_API_CLASS(Basis));
|
||||
CACHE_CLASS_AND_CHECK(Quaternion, GODOT_API_CLASS(Quaternion));
|
||||
CACHE_CLASS_AND_CHECK(Transform3D, GODOT_API_CLASS(Transform3D));
|
||||
CACHE_CLASS_AND_CHECK(AABB, GODOT_API_CLASS(AABB));
|
||||
CACHE_CLASS_AND_CHECK(Color, GODOT_API_CLASS(Color));
|
||||
CACHE_CLASS_AND_CHECK(Plane, GODOT_API_CLASS(Plane));
|
||||
CACHE_CLASS_AND_CHECK(StringName, GODOT_API_CLASS(StringName));
|
||||
CACHE_CLASS_AND_CHECK(NodePath, GODOT_API_CLASS(NodePath));
|
||||
CACHE_CLASS_AND_CHECK(RID, GODOT_API_CLASS(RID));
|
||||
CACHE_CLASS_AND_CHECK(GodotObject, GODOT_API_CLASS(Object));
|
||||
CACHE_CLASS_AND_CHECK(GodotResource, GODOT_API_CLASS(Resource));
|
||||
CACHE_CLASS_AND_CHECK(Node, GODOT_API_CLASS(Node));
|
||||
CACHE_CLASS_AND_CHECK(Control, GODOT_API_CLASS(Control));
|
||||
CACHE_CLASS_AND_CHECK(Node3D, GODOT_API_CLASS(Node3D));
|
||||
CACHE_CLASS_AND_CHECK(WeakRef, GODOT_API_CLASS(WeakRef));
|
||||
CACHE_CLASS_AND_CHECK(Callable, GODOT_API_CLASS(Callable));
|
||||
CACHE_CLASS_AND_CHECK(SignalInfo, GODOT_API_CLASS(SignalInfo));
|
||||
CACHE_CLASS_AND_CHECK(Array, GODOT_API_NS_CLASS(BINDINGS_NAMESPACE_COLLECTIONS, Array));
|
||||
CACHE_CLASS_AND_CHECK(Dictionary, GODOT_API_NS_CLASS(BINDINGS_NAMESPACE_COLLECTIONS, Dictionary));
|
||||
CACHE_CLASS_AND_CHECK(MarshalUtils, GODOT_API_CLASS(MarshalUtils));
|
||||
CACHE_CLASS_AND_CHECK(ISerializationListener, GODOT_API_CLASS(ISerializationListener));
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
@ -278,36 +185,38 @@ void update_godot_api_cache() {
|
|||
CACHE_FIELD_AND_CHECK(AssemblyHasScriptsAttribute, scriptTypes, CACHED_CLASS(AssemblyHasScriptsAttribute)->get_field("scriptTypes"));
|
||||
|
||||
CACHE_FIELD_AND_CHECK(GodotObject, ptr, CACHED_CLASS(GodotObject)->get_field(BINDINGS_PTR_FIELD));
|
||||
CACHE_FIELD_AND_CHECK(StringName, ptr, CACHED_CLASS(StringName)->get_field(BINDINGS_PTR_FIELD));
|
||||
CACHE_FIELD_AND_CHECK(NodePath, ptr, CACHED_CLASS(NodePath)->get_field(BINDINGS_PTR_FIELD));
|
||||
CACHE_FIELD_AND_CHECK(RID, ptr, CACHED_CLASS(RID)->get_field(BINDINGS_PTR_FIELD));
|
||||
|
||||
CACHE_METHOD_THUNK_AND_CHECK(GodotObject, Dispose, CACHED_CLASS(GodotObject)->get_method("Dispose", 0));
|
||||
CACHE_METHOD_THUNK_AND_CHECK(Array, GetPtr, GODOT_API_NS_CLASS(BINDINGS_NAMESPACE_COLLECTIONS, Array)->get_method("GetPtr", 0));
|
||||
CACHE_METHOD_THUNK_AND_CHECK(Dictionary, GetPtr, GODOT_API_NS_CLASS(BINDINGS_NAMESPACE_COLLECTIONS, Dictionary)->get_method("GetPtr", 0));
|
||||
CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, SignalCallback, GODOT_API_CLASS(SignalAwaiter)->get_method("SignalCallback", 1));
|
||||
CACHE_METHOD_THUNK_AND_CHECK(GodotTaskScheduler, Activate, GODOT_API_CLASS(GodotTaskScheduler)->get_method("Activate", 0));
|
||||
|
||||
CACHE_METHOD_THUNK_AND_CHECK(DelegateUtils, TrySerializeDelegateWithGCHandle, GODOT_API_CLASS(DelegateUtils)->get_method("TrySerializeDelegateWithGCHandle", 2));
|
||||
CACHE_METHOD_THUNK_AND_CHECK(DelegateUtils, TryDeserializeDelegateWithGCHandle, GODOT_API_CLASS(DelegateUtils)->get_method("TryDeserializeDelegateWithGCHandle", 2));
|
||||
CACHE_METHOD_THUNK_AND_CHECK(DelegateUtils, TrySerializeDelegate, GODOT_API_CLASS(DelegateUtils)->get_method("TrySerializeDelegate", 2));
|
||||
CACHE_METHOD_THUNK_AND_CHECK(DelegateUtils, TryDeserializeDelegate, GODOT_API_CLASS(DelegateUtils)->get_method("TryDeserializeDelegate", 2));
|
||||
CACHE_METHOD_THUNK_AND_CHECK(DelegateUtils, InvokeWithVariantArgs, GODOT_API_CLASS(DelegateUtils)->get_method("InvokeWithVariantArgs", 4));
|
||||
CACHE_METHOD_THUNK_AND_CHECK(DelegateUtils, DelegateEquals, GODOT_API_CLASS(DelegateUtils)->get_method("DelegateEquals", 2));
|
||||
CACHE_METHOD_THUNK_AND_CHECK(DelegateUtils, FreeGCHandle, GODOT_API_CLASS(DelegateUtils)->get_method("FreeGCHandle", 1));
|
||||
|
||||
// Start of MarshalUtils methods
|
||||
GDMonoClass *gd_mono_marshal_class = GDMono::get_singleton()->get_core_api_assembly()->get_class(
|
||||
"Godot.NativeInterop", "Marshaling");
|
||||
|
||||
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericArray, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsGenericArray", 1));
|
||||
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericDictionary, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsGenericDictionary", 1));
|
||||
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsSystemGenericList, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsSystemGenericList", 1));
|
||||
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsSystemGenericDictionary, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsSystemGenericDictionary", 1));
|
||||
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericIEnumerable, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsGenericIEnumerable", 1));
|
||||
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericICollection, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsGenericICollection", 1));
|
||||
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, TypeIsGenericIDictionary, GODOT_API_CLASS(MarshalUtils)->get_method("TypeIsGenericIDictionary", 1));
|
||||
ERR_FAIL_COND_MSG(gd_mono_marshal_class == nullptr,
|
||||
"Mono Cache: Class `Godot.NativeInterop.Marshaling` not found.");
|
||||
|
||||
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, ArrayGetElementType, GODOT_API_CLASS(MarshalUtils)->get_method("ArrayGetElementType", 2));
|
||||
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, DictionaryGetKeyValueTypes, GODOT_API_CLASS(MarshalUtils)->get_method("DictionaryGetKeyValueTypes", 3));
|
||||
CACHE_METHOD_THUNK_AND_CHECK(Marshaling, managed_to_variant_type,
|
||||
gd_mono_marshal_class->get_method("managed_to_variant_type", 2));
|
||||
CACHE_METHOD_THUNK_AND_CHECK(Marshaling, try_get_array_element_type,
|
||||
gd_mono_marshal_class->get_method("try_get_array_element_type", 2));
|
||||
CACHE_METHOD_THUNK_AND_CHECK(Marshaling, variant_to_mono_object_of_type,
|
||||
gd_mono_marshal_class->get_method("variant_to_mono_object_of_type", 2));
|
||||
CACHE_METHOD_THUNK_AND_CHECK(Marshaling, variant_to_mono_object,
|
||||
gd_mono_marshal_class->get_method("variant_to_mono_object", 1));
|
||||
CACHE_METHOD_THUNK_AND_CHECK(Marshaling, mono_object_to_variant_out,
|
||||
gd_mono_marshal_class->get_method("mono_object_to_variant_out", 3));
|
||||
|
||||
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, MakeGenericArrayType, GODOT_API_CLASS(MarshalUtils)->get_method("MakeGenericArrayType", 1));
|
||||
CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, MakeGenericDictionaryType, GODOT_API_CLASS(MarshalUtils)->get_method("MakeGenericDictionaryType", 2));
|
||||
|
||||
// End of MarshalUtils methods
|
||||
CACHE_METHOD_THUNK_AND_CHECK(Marshaling, SetFieldValue,
|
||||
gd_mono_marshal_class->get_method("SetFieldValue", 3));
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
CACHE_METHOD_THUNK_AND_CHECK(DebuggingUtils, GetStackFrameInfo, GODOT_API_CLASS(DebuggingUtils)->get_method("GetStackFrameInfo", 4));
|
||||
|
|
|
@ -42,23 +42,7 @@ struct CachedData {
|
|||
|
||||
// Let's use the no-namespace format for these too
|
||||
GDMonoClass *class_MonoObject; // object
|
||||
GDMonoClass *class_bool; // bool
|
||||
GDMonoClass *class_int8_t; // sbyte
|
||||
GDMonoClass *class_int16_t; // short
|
||||
GDMonoClass *class_int32_t; // int
|
||||
GDMonoClass *class_int64_t; // long
|
||||
GDMonoClass *class_uint8_t; // byte
|
||||
GDMonoClass *class_uint16_t; // ushort
|
||||
GDMonoClass *class_uint32_t; // uint
|
||||
GDMonoClass *class_uint64_t; // ulong
|
||||
GDMonoClass *class_float; // float
|
||||
GDMonoClass *class_double; // double
|
||||
GDMonoClass *class_String; // string
|
||||
GDMonoClass *class_IntPtr; // System.IntPtr
|
||||
|
||||
GDMonoClass *class_System_Collections_IEnumerable;
|
||||
GDMonoClass *class_System_Collections_ICollection;
|
||||
GDMonoClass *class_System_Collections_IDictionary;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
GDMonoClass *class_System_Diagnostics_StackTrace;
|
||||
|
@ -68,37 +52,13 @@ struct CachedData {
|
|||
#endif
|
||||
|
||||
GDMonoClass *class_KeyNotFoundException;
|
||||
|
||||
MonoClass *rawclass_Dictionary;
|
||||
// -----------------------------------------------
|
||||
|
||||
GDMonoClass *class_Vector2;
|
||||
GDMonoClass *class_Vector2i;
|
||||
GDMonoClass *class_Rect2;
|
||||
GDMonoClass *class_Rect2i;
|
||||
GDMonoClass *class_Transform2D;
|
||||
GDMonoClass *class_Vector3;
|
||||
GDMonoClass *class_Vector3i;
|
||||
GDMonoClass *class_Basis;
|
||||
GDMonoClass *class_Quaternion;
|
||||
GDMonoClass *class_Transform3D;
|
||||
GDMonoClass *class_AABB;
|
||||
GDMonoClass *class_Color;
|
||||
GDMonoClass *class_Plane;
|
||||
GDMonoClass *class_StringName;
|
||||
GDMonoClass *class_NodePath;
|
||||
GDMonoClass *class_RID;
|
||||
GDMonoClass *class_GodotObject;
|
||||
GDMonoClass *class_GodotResource;
|
||||
GDMonoClass *class_Node;
|
||||
GDMonoClass *class_Control;
|
||||
GDMonoClass *class_Node3D;
|
||||
GDMonoClass *class_WeakRef;
|
||||
GDMonoClass *class_Callable;
|
||||
GDMonoClass *class_SignalInfo;
|
||||
GDMonoClass *class_Array;
|
||||
GDMonoClass *class_Dictionary;
|
||||
GDMonoClass *class_MarshalUtils;
|
||||
GDMonoClass *class_ISerializationListener;
|
||||
|
||||
#ifdef DEBUG_ENABLED
|
||||
|
@ -123,39 +83,30 @@ struct CachedData {
|
|||
GDMonoField *field_AssemblyHasScriptsAttribute_scriptTypes;
|
||||
|
||||
GDMonoField *field_GodotObject_ptr;
|
||||
GDMonoField *field_StringName_ptr;
|
||||
GDMonoField *field_NodePath_ptr;
|
||||
GDMonoField *field_Image_ptr;
|
||||
GDMonoField *field_RID_ptr;
|
||||
|
||||
GDMonoMethodThunk<MonoObject *> methodthunk_GodotObject_Dispose;
|
||||
GDMonoMethodThunkR<Array *, MonoObject *> methodthunk_Array_GetPtr;
|
||||
GDMonoMethodThunkR<Dictionary *, MonoObject *> methodthunk_Dictionary_GetPtr;
|
||||
GDMonoMethodThunk<MonoObject *, MonoArray *> methodthunk_SignalAwaiter_SignalCallback;
|
||||
GDMonoMethodThunk<MonoObject *> methodthunk_GodotTaskScheduler_Activate;
|
||||
|
||||
GDMonoMethodThunkR<MonoBoolean, MonoObject *, MonoObject *> methodthunk_Delegate_Equals;
|
||||
|
||||
GDMonoMethodThunkR<MonoBoolean, void *, MonoObject *> methodthunk_DelegateUtils_TrySerializeDelegateWithGCHandle;
|
||||
GDMonoMethodThunkR<MonoBoolean, MonoObject *, void **> methodthunk_DelegateUtils_TryDeserializeDelegateWithGCHandle;
|
||||
|
||||
GDMonoMethodThunkR<MonoBoolean, MonoDelegate *, MonoObject *> methodthunk_DelegateUtils_TrySerializeDelegate;
|
||||
GDMonoMethodThunkR<MonoBoolean, MonoObject *, MonoDelegate **> methodthunk_DelegateUtils_TryDeserializeDelegate;
|
||||
|
||||
// Start of MarshalUtils methods
|
||||
GDMonoMethodThunk<void *, const Variant **, uint32_t, const Variant *> methodthunk_DelegateUtils_InvokeWithVariantArgs;
|
||||
GDMonoMethodThunkR<MonoBoolean, void *, void *> methodthunk_DelegateUtils_DelegateEquals;
|
||||
GDMonoMethodThunk<void *> methodthunk_DelegateUtils_FreeGCHandle;
|
||||
|
||||
GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsGenericArray;
|
||||
GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsGenericDictionary;
|
||||
GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsSystemGenericList;
|
||||
GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsSystemGenericDictionary;
|
||||
GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsGenericIEnumerable;
|
||||
GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsGenericICollection;
|
||||
GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *> methodthunk_MarshalUtils_TypeIsGenericIDictionary;
|
||||
GDMonoMethodThunkR<int32_t, MonoReflectionType *, MonoBoolean *> methodthunk_Marshaling_managed_to_variant_type;
|
||||
GDMonoMethodThunkR<MonoBoolean, MonoReflectionType *, MonoReflectionType **> methodthunk_Marshaling_try_get_array_element_type;
|
||||
GDMonoMethodThunkR<MonoObject *, const Variant *, MonoReflectionType *> methodthunk_Marshaling_variant_to_mono_object_of_type;
|
||||
GDMonoMethodThunkR<MonoObject *, const Variant *> methodthunk_Marshaling_variant_to_mono_object;
|
||||
GDMonoMethodThunk<MonoObject *, MonoBoolean, Variant *> methodthunk_Marshaling_mono_object_to_variant_out;
|
||||
|
||||
GDMonoMethodThunk<MonoReflectionType *, MonoReflectionType **> methodthunk_MarshalUtils_ArrayGetElementType;
|
||||
GDMonoMethodThunk<MonoReflectionType *, MonoReflectionType **, MonoReflectionType **> methodthunk_MarshalUtils_DictionaryGetKeyValueTypes;
|
||||
|
||||
GDMonoMethodThunkR<MonoReflectionType *, MonoReflectionType *> methodthunk_MarshalUtils_MakeGenericArrayType;
|
||||
GDMonoMethodThunkR<MonoReflectionType *, MonoReflectionType *, MonoReflectionType *> methodthunk_MarshalUtils_MakeGenericDictionaryType;
|
||||
|
||||
// End of MarshalUtils methods
|
||||
GDMonoMethodThunk<MonoReflectionField *, MonoObject *, const Variant *> methodthunk_Marshaling_SetFieldValue;
|
||||
|
||||
Ref<MonoGCHandleRef> task_scheduler_handle;
|
||||
|
||||
|
@ -176,10 +127,6 @@ extern CachedData cached_data;
|
|||
void update_corlib_cache();
|
||||
void update_godot_api_cache();
|
||||
|
||||
inline void clear_corlib_cache() {
|
||||
cached_data.clear_corlib_cache();
|
||||
}
|
||||
|
||||
inline void clear_godot_api_cache() {
|
||||
cached_data.clear_godot_api_cache();
|
||||
}
|
||||
|
@ -187,10 +134,8 @@ inline void clear_godot_api_cache() {
|
|||
|
||||
#define CACHED_CLASS(m_class) (GDMonoCache::cached_data.class_##m_class)
|
||||
#define CACHED_CLASS_RAW(m_class) (GDMonoCache::cached_data.class_##m_class->get_mono_ptr())
|
||||
#define CACHED_RAW_MONO_CLASS(m_class) (GDMonoCache::cached_data.rawclass_##m_class)
|
||||
#define CACHED_FIELD(m_class, m_field) (GDMonoCache::cached_data.field_##m_class##_##m_field)
|
||||
#define CACHED_METHOD(m_class, m_method) (GDMonoCache::cached_data.method_##m_class##_##m_method)
|
||||
#define CACHED_METHOD_THUNK(m_class, m_method) (GDMonoCache::cached_data.methodthunk_##m_class##_##m_method)
|
||||
#define CACHED_PROPERTY(m_class, m_property) (GDMonoCache::cached_data.property_##m_class##_##m_property)
|
||||
|
||||
#endif // GD_MONO_CACHE_H
|
||||
|
|
|
@ -46,391 +46,14 @@ void GDMonoField::set_value_raw(MonoObject *p_object, void *p_ptr) {
|
|||
}
|
||||
|
||||
void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_value) {
|
||||
switch (type.type_encoding) {
|
||||
case MONO_TYPE_BOOLEAN: {
|
||||
MonoBoolean val = p_value.operator bool();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
} break;
|
||||
case MONO_TYPE_CHAR: {
|
||||
int16_t val = p_value.operator unsigned short();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
} break;
|
||||
case MONO_TYPE_I1: {
|
||||
int8_t val = p_value.operator signed char();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
} break;
|
||||
case MONO_TYPE_I2: {
|
||||
int16_t val = p_value.operator signed short();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
} break;
|
||||
case MONO_TYPE_I4: {
|
||||
int32_t val = p_value.operator signed int();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
} break;
|
||||
case MONO_TYPE_I8: {
|
||||
int64_t val = p_value.operator int64_t();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
} break;
|
||||
case MONO_TYPE_U1: {
|
||||
uint8_t val = p_value.operator unsigned char();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
} break;
|
||||
case MONO_TYPE_U2: {
|
||||
uint16_t val = p_value.operator unsigned short();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
} break;
|
||||
case MONO_TYPE_U4: {
|
||||
uint32_t val = p_value.operator unsigned int();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
} break;
|
||||
case MONO_TYPE_U8: {
|
||||
uint64_t val = p_value.operator uint64_t();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
} break;
|
||||
case MONO_TYPE_R4: {
|
||||
float val = p_value.operator float();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
} break;
|
||||
case MONO_TYPE_R8: {
|
||||
double val = p_value.operator double();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
} break;
|
||||
case MONO_TYPE_VALUETYPE: {
|
||||
GDMonoClass *tclass = type.type_class;
|
||||
MonoReflectionField *reflfield = mono_field_get_object(mono_domain_get(), owner->get_mono_ptr(), mono_field);
|
||||
|
||||
if (tclass == CACHED_CLASS(Vector2)) {
|
||||
GDMonoMarshal::M_Vector2 from = MARSHALLED_OUT(Vector2, p_value.operator ::Vector2());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
break;
|
||||
}
|
||||
MonoException *exc = nullptr;
|
||||
CACHED_METHOD_THUNK(Marshaling, SetFieldValue)
|
||||
.invoke(reflfield, p_object, &p_value, &exc);
|
||||
|
||||
if (tclass == CACHED_CLASS(Vector2i)) {
|
||||
GDMonoMarshal::M_Vector2i from = MARSHALLED_OUT(Vector2i, p_value.operator ::Vector2i());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tclass == CACHED_CLASS(Rect2)) {
|
||||
GDMonoMarshal::M_Rect2 from = MARSHALLED_OUT(Rect2, p_value.operator ::Rect2());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tclass == CACHED_CLASS(Rect2i)) {
|
||||
GDMonoMarshal::M_Rect2i from = MARSHALLED_OUT(Rect2i, p_value.operator ::Rect2i());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tclass == CACHED_CLASS(Transform2D)) {
|
||||
GDMonoMarshal::M_Transform2D from = MARSHALLED_OUT(Transform2D, p_value.operator ::Transform2D());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tclass == CACHED_CLASS(Vector3)) {
|
||||
GDMonoMarshal::M_Vector3 from = MARSHALLED_OUT(Vector3, p_value.operator ::Vector3());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tclass == CACHED_CLASS(Vector3i)) {
|
||||
GDMonoMarshal::M_Vector3i from = MARSHALLED_OUT(Vector3i, p_value.operator ::Vector3i());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tclass == CACHED_CLASS(Basis)) {
|
||||
GDMonoMarshal::M_Basis from = MARSHALLED_OUT(Basis, p_value.operator ::Basis());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tclass == CACHED_CLASS(Quaternion)) {
|
||||
GDMonoMarshal::M_Quaternion from = MARSHALLED_OUT(Quaternion, p_value.operator ::Quaternion());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tclass == CACHED_CLASS(Transform3D)) {
|
||||
GDMonoMarshal::M_Transform3D from = MARSHALLED_OUT(Transform3D, p_value.operator ::Transform3D());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tclass == CACHED_CLASS(AABB)) {
|
||||
GDMonoMarshal::M_AABB from = MARSHALLED_OUT(AABB, p_value.operator ::AABB());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tclass == CACHED_CLASS(Color)) {
|
||||
GDMonoMarshal::M_Color from = MARSHALLED_OUT(Color, p_value.operator ::Color());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tclass == CACHED_CLASS(Plane)) {
|
||||
GDMonoMarshal::M_Plane from = MARSHALLED_OUT(Plane, p_value.operator ::Plane());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tclass == CACHED_CLASS(Callable)) {
|
||||
GDMonoMarshal::M_Callable val = GDMonoMarshal::callable_to_managed(p_value.operator Callable());
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
break;
|
||||
}
|
||||
|
||||
if (tclass == CACHED_CLASS(SignalInfo)) {
|
||||
GDMonoMarshal::M_SignalInfo val = GDMonoMarshal::signal_info_to_managed(p_value.operator Signal());
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
break;
|
||||
}
|
||||
|
||||
if (mono_class_is_enum(tclass->get_mono_ptr())) {
|
||||
MonoType *enum_basetype = mono_class_enum_basetype(tclass->get_mono_ptr());
|
||||
switch (mono_type_get_type(enum_basetype)) {
|
||||
case MONO_TYPE_BOOLEAN: {
|
||||
MonoBoolean val = p_value.operator bool();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
break;
|
||||
}
|
||||
case MONO_TYPE_CHAR: {
|
||||
uint16_t val = p_value.operator unsigned short();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
break;
|
||||
}
|
||||
case MONO_TYPE_I1: {
|
||||
int8_t val = p_value.operator signed char();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
break;
|
||||
}
|
||||
case MONO_TYPE_I2: {
|
||||
int16_t val = p_value.operator signed short();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
break;
|
||||
}
|
||||
case MONO_TYPE_I4: {
|
||||
int32_t val = p_value.operator signed int();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
break;
|
||||
}
|
||||
case MONO_TYPE_I8: {
|
||||
int64_t val = p_value.operator int64_t();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
break;
|
||||
}
|
||||
case MONO_TYPE_U1: {
|
||||
uint8_t val = p_value.operator unsigned char();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
break;
|
||||
}
|
||||
case MONO_TYPE_U2: {
|
||||
uint16_t val = p_value.operator unsigned short();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
break;
|
||||
}
|
||||
case MONO_TYPE_U4: {
|
||||
uint32_t val = p_value.operator unsigned int();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
break;
|
||||
}
|
||||
case MONO_TYPE_U8: {
|
||||
uint64_t val = p_value.operator uint64_t();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
ERR_FAIL_MSG("Attempted to convert Variant to a managed enum value of unmarshallable base type.");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ERR_FAIL_MSG("Attempted to set the value of a field of unmarshallable type: '" + tclass->get_name() + "'.");
|
||||
} break;
|
||||
case MONO_TYPE_STRING: {
|
||||
if (p_value.get_type() == Variant::NIL) {
|
||||
// Otherwise, Variant -> String would return the string "Null"
|
||||
MonoString *mono_string = nullptr;
|
||||
mono_field_set_value(p_object, mono_field, mono_string);
|
||||
} else {
|
||||
MonoString *mono_string = GDMonoMarshal::mono_string_from_godot(p_value);
|
||||
mono_field_set_value(p_object, mono_field, mono_string);
|
||||
}
|
||||
} break;
|
||||
case MONO_TYPE_ARRAY:
|
||||
case MONO_TYPE_SZARRAY: {
|
||||
MonoArray *managed = GDMonoMarshal::variant_to_mono_array(p_value, type.type_class);
|
||||
if (likely(managed != nullptr)) {
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
}
|
||||
} break;
|
||||
case MONO_TYPE_CLASS: {
|
||||
MonoObject *managed = GDMonoMarshal::variant_to_mono_object_of_class(p_value, type.type_class);
|
||||
if (likely(managed != nullptr)) {
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
}
|
||||
} break;
|
||||
case MONO_TYPE_GENERICINST: {
|
||||
MonoObject *managed = GDMonoMarshal::variant_to_mono_object_of_genericinst(p_value, type.type_class);
|
||||
if (likely(managed != nullptr)) {
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
}
|
||||
} break;
|
||||
case MONO_TYPE_OBJECT: {
|
||||
// Variant
|
||||
switch (p_value.get_type()) {
|
||||
case Variant::BOOL: {
|
||||
MonoBoolean val = p_value.operator bool();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
} break;
|
||||
case Variant::INT: {
|
||||
int32_t val = p_value.operator signed int();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
} break;
|
||||
case Variant::FLOAT: {
|
||||
#ifdef REAL_T_IS_DOUBLE
|
||||
double val = p_value.operator double();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
#else
|
||||
float val = p_value.operator float();
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
#endif
|
||||
} break;
|
||||
case Variant::STRING: {
|
||||
MonoString *mono_string = GDMonoMarshal::mono_string_from_godot(p_value);
|
||||
mono_field_set_value(p_object, mono_field, mono_string);
|
||||
} break;
|
||||
case Variant::VECTOR2: {
|
||||
GDMonoMarshal::M_Vector2 from = MARSHALLED_OUT(Vector2, p_value.operator ::Vector2());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
} break;
|
||||
case Variant::VECTOR2I: {
|
||||
GDMonoMarshal::M_Vector2i from = MARSHALLED_OUT(Vector2i, p_value.operator ::Vector2i());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
} break;
|
||||
case Variant::RECT2: {
|
||||
GDMonoMarshal::M_Rect2 from = MARSHALLED_OUT(Rect2, p_value.operator ::Rect2());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
} break;
|
||||
case Variant::RECT2I: {
|
||||
GDMonoMarshal::M_Rect2i from = MARSHALLED_OUT(Rect2i, p_value.operator ::Rect2i());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
} break;
|
||||
case Variant::VECTOR3: {
|
||||
GDMonoMarshal::M_Vector3 from = MARSHALLED_OUT(Vector3, p_value.operator ::Vector3());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
} break;
|
||||
case Variant::VECTOR3I: {
|
||||
GDMonoMarshal::M_Vector3i from = MARSHALLED_OUT(Vector3i, p_value.operator ::Vector3i());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
} break;
|
||||
case Variant::TRANSFORM2D: {
|
||||
GDMonoMarshal::M_Transform2D from = MARSHALLED_OUT(Transform2D, p_value.operator ::Transform2D());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
} break;
|
||||
case Variant::PLANE: {
|
||||
GDMonoMarshal::M_Plane from = MARSHALLED_OUT(Plane, p_value.operator ::Plane());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
} break;
|
||||
case Variant::QUATERNION: {
|
||||
GDMonoMarshal::M_Quaternion from = MARSHALLED_OUT(Quaternion, p_value.operator ::Quaternion());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
} break;
|
||||
case Variant::AABB: {
|
||||
GDMonoMarshal::M_AABB from = MARSHALLED_OUT(AABB, p_value.operator ::AABB());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
} break;
|
||||
case Variant::BASIS: {
|
||||
GDMonoMarshal::M_Basis from = MARSHALLED_OUT(Basis, p_value.operator ::Basis());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
} break;
|
||||
case Variant::TRANSFORM3D: {
|
||||
GDMonoMarshal::M_Transform3D from = MARSHALLED_OUT(Transform3D, p_value.operator ::Transform3D());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
} break;
|
||||
case Variant::COLOR: {
|
||||
GDMonoMarshal::M_Color from = MARSHALLED_OUT(Color, p_value.operator ::Color());
|
||||
mono_field_set_value(p_object, mono_field, &from);
|
||||
} break;
|
||||
case Variant::STRING_NAME: {
|
||||
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator StringName());
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
} break;
|
||||
case Variant::NODE_PATH: {
|
||||
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator NodePath());
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
} break;
|
||||
case Variant::RID: {
|
||||
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator ::RID());
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
} break;
|
||||
case Variant::OBJECT: {
|
||||
MonoObject *managed = GDMonoUtils::unmanaged_get_managed(p_value.operator Object *());
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
} break;
|
||||
case Variant::CALLABLE: {
|
||||
GDMonoMarshal::M_Callable val = GDMonoMarshal::callable_to_managed(p_value.operator Callable());
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
} break;
|
||||
case Variant::SIGNAL: {
|
||||
GDMonoMarshal::M_SignalInfo val = GDMonoMarshal::signal_info_to_managed(p_value.operator Signal());
|
||||
mono_field_set_value(p_object, mono_field, &val);
|
||||
} break;
|
||||
case Variant::DICTIONARY: {
|
||||
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), CACHED_CLASS(Dictionary));
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
} break;
|
||||
case Variant::ARRAY: {
|
||||
MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), CACHED_CLASS(Array));
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
} break;
|
||||
case Variant::PACKED_BYTE_ARRAY: {
|
||||
MonoArray *managed = GDMonoMarshal::PackedByteArray_to_mono_array(p_value.operator ::PackedByteArray());
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
} break;
|
||||
case Variant::PACKED_INT32_ARRAY: {
|
||||
MonoArray *managed = GDMonoMarshal::PackedInt32Array_to_mono_array(p_value.operator ::PackedInt32Array());
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
} break;
|
||||
case Variant::PACKED_INT64_ARRAY: {
|
||||
MonoArray *managed = GDMonoMarshal::PackedInt64Array_to_mono_array(p_value.operator ::PackedInt64Array());
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
} break;
|
||||
case Variant::PACKED_FLOAT32_ARRAY: {
|
||||
MonoArray *managed = GDMonoMarshal::PackedFloat32Array_to_mono_array(p_value.operator ::PackedFloat32Array());
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
} break;
|
||||
case Variant::PACKED_FLOAT64_ARRAY: {
|
||||
MonoArray *managed = GDMonoMarshal::PackedFloat64Array_to_mono_array(p_value.operator ::PackedFloat64Array());
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
} break;
|
||||
case Variant::PACKED_STRING_ARRAY: {
|
||||
MonoArray *managed = GDMonoMarshal::PackedStringArray_to_mono_array(p_value.operator ::PackedStringArray());
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
} break;
|
||||
case Variant::PACKED_VECTOR2_ARRAY: {
|
||||
MonoArray *managed = GDMonoMarshal::PackedVector2Array_to_mono_array(p_value.operator ::PackedVector2Array());
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
} break;
|
||||
case Variant::PACKED_VECTOR3_ARRAY: {
|
||||
MonoArray *managed = GDMonoMarshal::PackedVector3Array_to_mono_array(p_value.operator ::PackedVector3Array());
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
} break;
|
||||
case Variant::PACKED_COLOR_ARRAY: {
|
||||
MonoArray *managed = GDMonoMarshal::PackedColorArray_to_mono_array(p_value.operator ::PackedColorArray());
|
||||
mono_field_set_value(p_object, mono_field, managed);
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
default: {
|
||||
ERR_PRINT("Attempted to set the value of a field of unexpected type encoding: " + itos(type.type_encoding) + ".");
|
||||
} break;
|
||||
if (exc) {
|
||||
GDMonoUtils::debug_print_unhandled_exception(exc);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -33,7 +33,6 @@
|
|||
|
||||
#include "core/variant/variant.h"
|
||||
|
||||
#include "../managed_callable.h"
|
||||
#include "gd_mono.h"
|
||||
#include "gd_mono_utils.h"
|
||||
|
||||
|
@ -44,25 +43,6 @@ T unbox(MonoObject *p_obj) {
|
|||
return *(T *)mono_object_unbox(p_obj);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *unbox_addr(MonoObject *p_obj) {
|
||||
return (T *)mono_object_unbox(p_obj);
|
||||
}
|
||||
|
||||
#define BOX_DOUBLE(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(double), &x)
|
||||
#define BOX_FLOAT(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(float), &x)
|
||||
#define BOX_INT64(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(int64_t), &x)
|
||||
#define BOX_INT32(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(int32_t), &x)
|
||||
#define BOX_INT16(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(int16_t), &x)
|
||||
#define BOX_INT8(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(int8_t), &x)
|
||||
#define BOX_UINT64(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(uint64_t), &x)
|
||||
#define BOX_UINT32(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(uint32_t), &x)
|
||||
#define BOX_UINT16(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(uint16_t), &x)
|
||||
#define BOX_UINT8(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(uint8_t), &x)
|
||||
#define BOX_BOOLEAN(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(bool), &x)
|
||||
#define BOX_PTR(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(IntPtr), x)
|
||||
#define BOX_ENUM(m_enum_class, x) mono_value_box(mono_domain_get(), m_enum_class, &x)
|
||||
|
||||
Variant::Type managed_to_variant_type(const ManagedType &p_type, bool *r_nil_is_variant = nullptr);
|
||||
|
||||
bool try_get_array_element_type(const ManagedType &p_array_type, ManagedType &r_elem_type);
|
||||
|
@ -90,457 +70,37 @@ _FORCE_INLINE_ MonoString *mono_string_from_godot(const String &p_string) {
|
|||
|
||||
// Variant
|
||||
|
||||
size_t variant_get_managed_unboxed_size(const ManagedType &p_type);
|
||||
void *variant_to_managed_unboxed(const Variant &p_var, const ManagedType &p_type, void *r_buffer, unsigned int &r_offset);
|
||||
MonoObject *variant_to_mono_object(const Variant &p_var, const ManagedType &p_type);
|
||||
MonoObject *variant_to_mono_object_of_type(const Variant &p_var, const ManagedType &p_type);
|
||||
|
||||
MonoObject *variant_to_mono_object(const Variant &p_var);
|
||||
MonoArray *variant_to_mono_array(const Variant &p_var, GDMonoClass *p_type_class);
|
||||
MonoObject *variant_to_mono_object_of_class(const Variant &p_var, GDMonoClass *p_type_class);
|
||||
MonoObject *variant_to_mono_object_of_genericinst(const Variant &p_var, GDMonoClass *p_type_class);
|
||||
MonoString *variant_to_mono_string(const Variant &p_var);
|
||||
|
||||
// These overloads were added to avoid passing a `const Variant *` to the `const Variant &`
|
||||
// parameter. That would result in the `Variant(bool)` copy constructor being called as
|
||||
// pointers are implicitly converted to bool. Implicit conversions are f-ing evil.
|
||||
|
||||
_FORCE_INLINE_ void *variant_to_managed_unboxed(const Variant *p_var, const ManagedType &p_type, void *r_buffer, unsigned int &r_offset) {
|
||||
return variant_to_managed_unboxed(*p_var, p_type, r_buffer, r_offset);
|
||||
}
|
||||
_FORCE_INLINE_ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_type) {
|
||||
return variant_to_mono_object(*p_var, p_type);
|
||||
_FORCE_INLINE_ MonoObject *variant_to_mono_object_of_type(const Variant *p_var, const ManagedType &p_type) {
|
||||
return variant_to_mono_object_of_type(*p_var, p_type);
|
||||
}
|
||||
_FORCE_INLINE_ MonoObject *variant_to_mono_object(const Variant *p_var) {
|
||||
return variant_to_mono_object(*p_var);
|
||||
}
|
||||
_FORCE_INLINE_ MonoArray *variant_to_mono_array(const Variant *p_var, GDMonoClass *p_type_class) {
|
||||
return variant_to_mono_array(*p_var, p_type_class);
|
||||
}
|
||||
_FORCE_INLINE_ MonoObject *variant_to_mono_object_of_class(const Variant *p_var, GDMonoClass *p_type_class) {
|
||||
return variant_to_mono_object_of_class(*p_var, p_type_class);
|
||||
}
|
||||
_FORCE_INLINE_ MonoObject *variant_to_mono_object_of_genericinst(const Variant *p_var, GDMonoClass *p_type_class) {
|
||||
return variant_to_mono_object_of_genericinst(*p_var, p_type_class);
|
||||
}
|
||||
_FORCE_INLINE_ MonoString *variant_to_mono_string(const Variant *p_var) {
|
||||
return variant_to_mono_string(*p_var);
|
||||
}
|
||||
|
||||
Variant mono_object_to_variant(MonoObject *p_obj);
|
||||
Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type);
|
||||
Variant mono_object_to_variant_no_err(MonoObject *p_obj, const ManagedType &p_type);
|
||||
Variant mono_object_to_variant_no_err(MonoObject *p_obj);
|
||||
|
||||
/// Tries to convert the MonoObject* to Variant and then convert the Variant to String.
|
||||
/// If the MonoObject* cannot be converted to Variant, then 'ToString()' is called instead.
|
||||
String mono_object_to_variant_string(MonoObject *p_obj, MonoException **r_exc);
|
||||
|
||||
// System.Collections.Generic
|
||||
|
||||
MonoObject *Dictionary_to_system_generic_dict(const Dictionary &p_dict, GDMonoClass *p_class, MonoReflectionType *p_key_reftype, MonoReflectionType *p_value_reftype);
|
||||
Dictionary system_generic_dict_to_Dictionary(MonoObject *p_obj, GDMonoClass *p_class, MonoReflectionType *p_key_reftype, MonoReflectionType *p_value_reftype);
|
||||
|
||||
MonoObject *Array_to_system_generic_list(const Array &p_array, GDMonoClass *p_class, MonoReflectionType *p_elem_reftype);
|
||||
Variant system_generic_list_to_Array_variant(MonoObject *p_obj, GDMonoClass *p_class, MonoReflectionType *p_elem_reftype);
|
||||
|
||||
// Array
|
||||
|
||||
MonoArray *Array_to_mono_array(const Array &p_array);
|
||||
MonoArray *Array_to_mono_array(const Array &p_array, MonoClass *p_array_type_class);
|
||||
Array mono_array_to_Array(MonoArray *p_array);
|
||||
|
||||
// PackedInt32Array
|
||||
|
||||
MonoArray *PackedInt32Array_to_mono_array(const PackedInt32Array &p_array);
|
||||
PackedInt32Array mono_array_to_PackedInt32Array(MonoArray *p_array);
|
||||
|
||||
// PackedInt64Array
|
||||
|
||||
MonoArray *PackedInt64Array_to_mono_array(const PackedInt64Array &p_array);
|
||||
PackedInt64Array mono_array_to_PackedInt64Array(MonoArray *p_array);
|
||||
|
||||
// PackedByteArray
|
||||
|
||||
MonoArray *PackedByteArray_to_mono_array(const PackedByteArray &p_array);
|
||||
PackedByteArray mono_array_to_PackedByteArray(MonoArray *p_array);
|
||||
|
||||
// PackedFloat32Array
|
||||
|
||||
MonoArray *PackedFloat32Array_to_mono_array(const PackedFloat32Array &p_array);
|
||||
PackedFloat32Array mono_array_to_PackedFloat32Array(MonoArray *p_array);
|
||||
|
||||
// PackedFloat64Array
|
||||
|
||||
MonoArray *PackedFloat64Array_to_mono_array(const PackedFloat64Array &p_array);
|
||||
PackedFloat64Array mono_array_to_PackedFloat64Array(MonoArray *p_array);
|
||||
|
||||
// PackedStringArray
|
||||
|
||||
MonoArray *PackedStringArray_to_mono_array(const PackedStringArray &p_array);
|
||||
PackedStringArray mono_array_to_PackedStringArray(MonoArray *p_array);
|
||||
|
||||
// PackedColorArray
|
||||
|
||||
MonoArray *PackedColorArray_to_mono_array(const PackedColorArray &p_array);
|
||||
PackedColorArray mono_array_to_PackedColorArray(MonoArray *p_array);
|
||||
|
||||
// PackedVector2Array
|
||||
|
||||
MonoArray *PackedVector2Array_to_mono_array(const PackedVector2Array &p_array);
|
||||
PackedVector2Array mono_array_to_PackedVector2Array(MonoArray *p_array);
|
||||
|
||||
// PackedVector3Array
|
||||
|
||||
MonoArray *PackedVector3Array_to_mono_array(const PackedVector3Array &p_array);
|
||||
PackedVector3Array mono_array_to_PackedVector3Array(MonoArray *p_array);
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct M_Callable {
|
||||
MonoObject *target;
|
||||
MonoObject *method_string_name;
|
||||
MonoDelegate *delegate;
|
||||
};
|
||||
|
||||
struct M_SignalInfo {
|
||||
MonoObject *owner;
|
||||
MonoObject *name_string_name;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
// Callable
|
||||
Callable managed_to_callable(const M_Callable &p_managed_callable);
|
||||
M_Callable callable_to_managed(const Callable &p_callable);
|
||||
|
||||
// SignalInfo
|
||||
Signal managed_to_signal_info(const M_SignalInfo &p_managed_signal);
|
||||
M_SignalInfo signal_info_to_managed(const Signal &p_signal);
|
||||
|
||||
// Structures
|
||||
|
||||
namespace InteropLayout {
|
||||
|
||||
enum {
|
||||
MATCHES_int = (sizeof(int32_t) == sizeof(uint32_t)),
|
||||
|
||||
MATCHES_float = (sizeof(float) == sizeof(uint32_t)),
|
||||
|
||||
MATCHES_double = (sizeof(double) == sizeof(uint64_t)),
|
||||
|
||||
#ifdef REAL_T_IS_DOUBLE
|
||||
MATCHES_real_t = (sizeof(real_t) == sizeof(uint64_t)),
|
||||
#else
|
||||
MATCHES_real_t = (sizeof(real_t) == sizeof(uint32_t)),
|
||||
#endif
|
||||
|
||||
MATCHES_Vector2 = (MATCHES_real_t && (sizeof(Vector2) == (sizeof(real_t) * 2)) &&
|
||||
offsetof(Vector2, x) == (sizeof(real_t) * 0) &&
|
||||
offsetof(Vector2, y) == (sizeof(real_t) * 1)),
|
||||
|
||||
MATCHES_Vector2i = (MATCHES_int && (sizeof(Vector2i) == (sizeof(int32_t) * 2)) &&
|
||||
offsetof(Vector2i, x) == (sizeof(int32_t) * 0) &&
|
||||
offsetof(Vector2i, y) == (sizeof(int32_t) * 1)),
|
||||
|
||||
MATCHES_Rect2 = (MATCHES_Vector2 && (sizeof(Rect2) == (sizeof(Vector2) * 2)) &&
|
||||
offsetof(Rect2, position) == (sizeof(Vector2) * 0) &&
|
||||
offsetof(Rect2, size) == (sizeof(Vector2) * 1)),
|
||||
|
||||
MATCHES_Rect2i = (MATCHES_Vector2i && (sizeof(Rect2i) == (sizeof(Vector2i) * 2)) &&
|
||||
offsetof(Rect2i, position) == (sizeof(Vector2i) * 0) &&
|
||||
offsetof(Rect2i, size) == (sizeof(Vector2i) * 1)),
|
||||
|
||||
MATCHES_Transform2D = (MATCHES_Vector2 && (sizeof(Transform2D) == (sizeof(Vector2) * 3))), // No field offset required, it stores an array
|
||||
|
||||
MATCHES_Vector3 = (MATCHES_real_t && (sizeof(Vector3) == (sizeof(real_t) * 3)) &&
|
||||
offsetof(Vector3, x) == (sizeof(real_t) * 0) &&
|
||||
offsetof(Vector3, y) == (sizeof(real_t) * 1) &&
|
||||
offsetof(Vector3, z) == (sizeof(real_t) * 2)),
|
||||
|
||||
MATCHES_Vector3i = (MATCHES_int && (sizeof(Vector3i) == (sizeof(int32_t) * 3)) &&
|
||||
offsetof(Vector3i, x) == (sizeof(int32_t) * 0) &&
|
||||
offsetof(Vector3i, y) == (sizeof(int32_t) * 1) &&
|
||||
offsetof(Vector3i, z) == (sizeof(int32_t) * 2)),
|
||||
|
||||
MATCHES_Basis = (MATCHES_Vector3 && (sizeof(Basis) == (sizeof(Vector3) * 3))), // No field offset required, it stores an array
|
||||
|
||||
MATCHES_Quaternion = (MATCHES_real_t && (sizeof(Quaternion) == (sizeof(real_t) * 4)) &&
|
||||
offsetof(Quaternion, x) == (sizeof(real_t) * 0) &&
|
||||
offsetof(Quaternion, y) == (sizeof(real_t) * 1) &&
|
||||
offsetof(Quaternion, z) == (sizeof(real_t) * 2) &&
|
||||
offsetof(Quaternion, w) == (sizeof(real_t) * 3)),
|
||||
|
||||
MATCHES_Transform3D = (MATCHES_Basis && MATCHES_Vector3 && (sizeof(Transform3D) == (sizeof(Basis) + sizeof(Vector3))) &&
|
||||
offsetof(Transform3D, basis) == 0 &&
|
||||
offsetof(Transform3D, origin) == sizeof(Basis)),
|
||||
|
||||
MATCHES_AABB = (MATCHES_Vector3 && (sizeof(AABB) == (sizeof(Vector3) * 2)) &&
|
||||
offsetof(AABB, position) == (sizeof(Vector3) * 0) &&
|
||||
offsetof(AABB, size) == (sizeof(Vector3) * 1)),
|
||||
|
||||
MATCHES_Color = (MATCHES_float && (sizeof(Color) == (sizeof(float) * 4)) &&
|
||||
offsetof(Color, r) == (sizeof(float) * 0) &&
|
||||
offsetof(Color, g) == (sizeof(float) * 1) &&
|
||||
offsetof(Color, b) == (sizeof(float) * 2) &&
|
||||
offsetof(Color, a) == (sizeof(float) * 3)),
|
||||
|
||||
MATCHES_Plane = (MATCHES_Vector3 && MATCHES_real_t && (sizeof(Plane) == (sizeof(Vector3) + sizeof(real_t))) &&
|
||||
offsetof(Plane, normal) == 0 &&
|
||||
offsetof(Plane, d) == sizeof(Vector3))
|
||||
};
|
||||
|
||||
// In the future we may force this if we want to ref return these structs
|
||||
#ifdef GD_MONO_FORCE_INTEROP_STRUCT_COPY
|
||||
/* clang-format off */
|
||||
static_assert(MATCHES_Vector2 && MATCHES_Rect2 && MATCHES_Transform2D && MATCHES_Vector3 &&
|
||||
MATCHES_Basis && MATCHES_Quaternion && MATCHES_Transform3D && MATCHES_AABB && MATCHES_Color &&
|
||||
MATCHES_Plane && MATCHES_Vector2i && MATCHES_Rect2i && MATCHES_Vector3i);
|
||||
/* clang-format on */
|
||||
#endif
|
||||
} // namespace InteropLayout
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct M_Vector2 {
|
||||
real_t x, y;
|
||||
|
||||
static _FORCE_INLINE_ Vector2 convert_to(const M_Vector2 &p_from) {
|
||||
return Vector2(p_from.x, p_from.y);
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ M_Vector2 convert_from(const Vector2 &p_from) {
|
||||
M_Vector2 ret = { p_from.x, p_from.y };
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
struct M_Vector2i {
|
||||
int32_t x, y;
|
||||
|
||||
static _FORCE_INLINE_ Vector2i convert_to(const M_Vector2i &p_from) {
|
||||
return Vector2i(p_from.x, p_from.y);
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ M_Vector2i convert_from(const Vector2i &p_from) {
|
||||
M_Vector2i ret = { p_from.x, p_from.y };
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
struct M_Rect2 {
|
||||
M_Vector2 position;
|
||||
M_Vector2 size;
|
||||
|
||||
static _FORCE_INLINE_ Rect2 convert_to(const M_Rect2 &p_from) {
|
||||
return Rect2(M_Vector2::convert_to(p_from.position),
|
||||
M_Vector2::convert_to(p_from.size));
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ M_Rect2 convert_from(const Rect2 &p_from) {
|
||||
M_Rect2 ret = { M_Vector2::convert_from(p_from.position), M_Vector2::convert_from(p_from.size) };
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
struct M_Rect2i {
|
||||
M_Vector2i position;
|
||||
M_Vector2i size;
|
||||
|
||||
static _FORCE_INLINE_ Rect2i convert_to(const M_Rect2i &p_from) {
|
||||
return Rect2i(M_Vector2i::convert_to(p_from.position),
|
||||
M_Vector2i::convert_to(p_from.size));
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ M_Rect2i convert_from(const Rect2i &p_from) {
|
||||
M_Rect2i ret = { M_Vector2i::convert_from(p_from.position), M_Vector2i::convert_from(p_from.size) };
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
struct M_Transform2D {
|
||||
M_Vector2 elements[3];
|
||||
|
||||
static _FORCE_INLINE_ Transform2D convert_to(const M_Transform2D &p_from) {
|
||||
return Transform2D(p_from.elements[0].x, p_from.elements[0].y,
|
||||
p_from.elements[1].x, p_from.elements[1].y,
|
||||
p_from.elements[2].x, p_from.elements[2].y);
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ M_Transform2D convert_from(const Transform2D &p_from) {
|
||||
M_Transform2D ret = {
|
||||
M_Vector2::convert_from(p_from.elements[0]),
|
||||
M_Vector2::convert_from(p_from.elements[1]),
|
||||
M_Vector2::convert_from(p_from.elements[2])
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
struct M_Vector3 {
|
||||
real_t x, y, z;
|
||||
|
||||
static _FORCE_INLINE_ Vector3 convert_to(const M_Vector3 &p_from) {
|
||||
return Vector3(p_from.x, p_from.y, p_from.z);
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ M_Vector3 convert_from(const Vector3 &p_from) {
|
||||
M_Vector3 ret = { p_from.x, p_from.y, p_from.z };
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
struct M_Vector3i {
|
||||
int32_t x, y, z;
|
||||
|
||||
static _FORCE_INLINE_ Vector3i convert_to(const M_Vector3i &p_from) {
|
||||
return Vector3i(p_from.x, p_from.y, p_from.z);
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ M_Vector3i convert_from(const Vector3i &p_from) {
|
||||
M_Vector3i ret = { p_from.x, p_from.y, p_from.z };
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
struct M_Basis {
|
||||
M_Vector3 elements[3];
|
||||
|
||||
static _FORCE_INLINE_ Basis convert_to(const M_Basis &p_from) {
|
||||
return Basis(M_Vector3::convert_to(p_from.elements[0]),
|
||||
M_Vector3::convert_to(p_from.elements[1]),
|
||||
M_Vector3::convert_to(p_from.elements[2]));
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ M_Basis convert_from(const Basis &p_from) {
|
||||
M_Basis ret = {
|
||||
M_Vector3::convert_from(p_from.elements[0]),
|
||||
M_Vector3::convert_from(p_from.elements[1]),
|
||||
M_Vector3::convert_from(p_from.elements[2])
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
struct M_Quaternion {
|
||||
real_t x, y, z, w;
|
||||
|
||||
static _FORCE_INLINE_ Quaternion convert_to(const M_Quaternion &p_from) {
|
||||
return Quaternion(p_from.x, p_from.y, p_from.z, p_from.w);
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ M_Quaternion convert_from(const Quaternion &p_from) {
|
||||
M_Quaternion ret = { p_from.x, p_from.y, p_from.z, p_from.w };
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
struct M_Transform3D {
|
||||
M_Basis basis;
|
||||
M_Vector3 origin;
|
||||
|
||||
static _FORCE_INLINE_ Transform3D convert_to(const M_Transform3D &p_from) {
|
||||
return Transform3D(M_Basis::convert_to(p_from.basis), M_Vector3::convert_to(p_from.origin));
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ M_Transform3D convert_from(const Transform3D &p_from) {
|
||||
M_Transform3D ret = { M_Basis::convert_from(p_from.basis), M_Vector3::convert_from(p_from.origin) };
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
struct M_AABB {
|
||||
M_Vector3 position;
|
||||
M_Vector3 size;
|
||||
|
||||
static _FORCE_INLINE_ AABB convert_to(const M_AABB &p_from) {
|
||||
return AABB(M_Vector3::convert_to(p_from.position), M_Vector3::convert_to(p_from.size));
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ M_AABB convert_from(const AABB &p_from) {
|
||||
M_AABB ret = { M_Vector3::convert_from(p_from.position), M_Vector3::convert_from(p_from.size) };
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
struct M_Color {
|
||||
float r, g, b, a;
|
||||
|
||||
static _FORCE_INLINE_ Color convert_to(const M_Color &p_from) {
|
||||
return Color(p_from.r, p_from.g, p_from.b, p_from.a);
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ M_Color convert_from(const Color &p_from) {
|
||||
M_Color ret = { p_from.r, p_from.g, p_from.b, p_from.a };
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
struct M_Plane {
|
||||
M_Vector3 normal;
|
||||
real_t d;
|
||||
|
||||
static _FORCE_INLINE_ Plane convert_to(const M_Plane &p_from) {
|
||||
return Plane(M_Vector3::convert_to(p_from.normal), p_from.d);
|
||||
}
|
||||
|
||||
static _FORCE_INLINE_ M_Plane convert_from(const Plane &p_from) {
|
||||
M_Plane ret = { M_Vector3::convert_from(p_from.normal), p_from.d };
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#define DECL_TYPE_MARSHAL_TEMPLATES(m_type) \
|
||||
template <int> \
|
||||
_FORCE_INLINE_ m_type marshalled_in_##m_type##_impl(const M_##m_type *p_from); \
|
||||
\
|
||||
template <> \
|
||||
_FORCE_INLINE_ m_type marshalled_in_##m_type##_impl<0>(const M_##m_type *p_from) { \
|
||||
return M_##m_type::convert_to(*p_from); \
|
||||
} \
|
||||
\
|
||||
template <> \
|
||||
_FORCE_INLINE_ m_type marshalled_in_##m_type##_impl<1>(const M_##m_type *p_from) { \
|
||||
return *reinterpret_cast<const m_type *>(p_from); \
|
||||
} \
|
||||
\
|
||||
_FORCE_INLINE_ m_type marshalled_in_##m_type(const M_##m_type *p_from) { \
|
||||
return marshalled_in_##m_type##_impl<InteropLayout::MATCHES_##m_type>(p_from); \
|
||||
} \
|
||||
\
|
||||
template <int> \
|
||||
_FORCE_INLINE_ M_##m_type marshalled_out_##m_type##_impl(const m_type &p_from); \
|
||||
\
|
||||
template <> \
|
||||
_FORCE_INLINE_ M_##m_type marshalled_out_##m_type##_impl<0>(const m_type &p_from) { \
|
||||
return M_##m_type::convert_from(p_from); \
|
||||
} \
|
||||
\
|
||||
template <> \
|
||||
_FORCE_INLINE_ M_##m_type marshalled_out_##m_type##_impl<1>(const m_type &p_from) { \
|
||||
return *reinterpret_cast<const M_##m_type *>(&p_from); \
|
||||
} \
|
||||
\
|
||||
_FORCE_INLINE_ M_##m_type marshalled_out_##m_type(const m_type &p_from) { \
|
||||
return marshalled_out_##m_type##_impl<InteropLayout::MATCHES_##m_type>(p_from); \
|
||||
}
|
||||
|
||||
DECL_TYPE_MARSHAL_TEMPLATES(Vector2)
|
||||
DECL_TYPE_MARSHAL_TEMPLATES(Vector2i)
|
||||
DECL_TYPE_MARSHAL_TEMPLATES(Rect2)
|
||||
DECL_TYPE_MARSHAL_TEMPLATES(Rect2i)
|
||||
DECL_TYPE_MARSHAL_TEMPLATES(Transform2D)
|
||||
DECL_TYPE_MARSHAL_TEMPLATES(Vector3)
|
||||
DECL_TYPE_MARSHAL_TEMPLATES(Vector3i)
|
||||
DECL_TYPE_MARSHAL_TEMPLATES(Basis)
|
||||
DECL_TYPE_MARSHAL_TEMPLATES(Quaternion)
|
||||
DECL_TYPE_MARSHAL_TEMPLATES(Transform3D)
|
||||
DECL_TYPE_MARSHAL_TEMPLATES(AABB)
|
||||
DECL_TYPE_MARSHAL_TEMPLATES(Color)
|
||||
DECL_TYPE_MARSHAL_TEMPLATES(Plane)
|
||||
|
||||
#define MARSHALLED_IN(m_type, m_from_ptr) (GDMonoMarshal::marshalled_in_##m_type(m_from_ptr))
|
||||
#define MARSHALLED_OUT(m_type, m_from) (GDMonoMarshal::marshalled_out_##m_type(m_from))
|
||||
} // namespace GDMonoMarshal
|
||||
|
||||
#endif // GDMONOMARSHAL_H
|
||||
|
|
|
@ -75,10 +75,6 @@ void GDMonoMethod::_update_signature(MonoMethodSignature *p_method_sig) {
|
|||
// clear the cache
|
||||
method_info_fetched = false;
|
||||
method_info = MethodInfo();
|
||||
|
||||
for (int i = 0; i < params_count; i++) {
|
||||
params_buffer_size += GDMonoMarshal::variant_get_managed_unboxed_size(param_types[i]);
|
||||
}
|
||||
}
|
||||
|
||||
GDMonoClass *GDMonoMethod::get_enclosing_class() const {
|
||||
|
@ -111,15 +107,14 @@ MonoObject *GDMonoMethod::invoke(MonoObject *p_object, const Variant **p_params,
|
|||
MonoObject *ret;
|
||||
|
||||
if (params_count > 0) {
|
||||
void **params = (void **)alloca(params_count * sizeof(void *));
|
||||
uint8_t *buffer = (uint8_t *)alloca(params_buffer_size);
|
||||
unsigned int offset = 0;
|
||||
MonoArray *params = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), get_parameters_count());
|
||||
|
||||
for (int i = 0; i < params_count; i++) {
|
||||
params[i] = GDMonoMarshal::variant_to_managed_unboxed(p_params[i], param_types[i], buffer + offset, offset);
|
||||
MonoObject *boxed_param = GDMonoMarshal::variant_to_mono_object_of_type(p_params[i], param_types[i]);
|
||||
mono_array_setref(params, i, boxed_param);
|
||||
}
|
||||
|
||||
ret = GDMonoUtils::runtime_invoke(mono_method, p_object, params, &exc);
|
||||
ret = GDMonoUtils::runtime_invoke_array(mono_method, p_object, params, &exc);
|
||||
} else {
|
||||
ret = GDMonoUtils::runtime_invoke(mono_method, p_object, nullptr, &exc);
|
||||
}
|
||||
|
|
|
@ -39,7 +39,6 @@ class GDMonoMethod : public IMonoClassMember {
|
|||
StringName name;
|
||||
|
||||
uint16_t params_count;
|
||||
unsigned int params_buffer_size = 0;
|
||||
ManagedType return_type;
|
||||
Vector<ManagedType> param_types;
|
||||
|
||||
|
|
|
@ -170,13 +170,6 @@ void runtime_object_init(MonoObject *p_this_obj, GDMonoClass *p_class, MonoExcep
|
|||
ctor->invoke_raw(p_this_obj, nullptr, r_exc);
|
||||
}
|
||||
|
||||
bool mono_delegate_equal(MonoDelegate *p_a, MonoDelegate *p_b) {
|
||||
MonoException *exc = nullptr;
|
||||
MonoBoolean res = CACHED_METHOD_THUNK(Delegate, Equals).invoke((MonoObject *)p_a, (MonoObject *)p_b, &exc);
|
||||
UNHANDLED_EXCEPTION(exc);
|
||||
return (bool)res;
|
||||
}
|
||||
|
||||
GDMonoClass *get_object_class(MonoObject *p_object) {
|
||||
return GDMono::get_singleton()->get_class(mono_object_get_class(p_object));
|
||||
}
|
||||
|
@ -239,102 +232,6 @@ MonoObject *create_managed_for_godot_object(GDMonoClass *p_class, const StringNa
|
|||
return mono_object;
|
||||
}
|
||||
|
||||
MonoObject *create_managed_from(const StringName &p_from) {
|
||||
MonoObject *mono_object = mono_object_new(mono_domain_get(), CACHED_CLASS_RAW(StringName));
|
||||
ERR_FAIL_NULL_V(mono_object, nullptr);
|
||||
|
||||
// Construct
|
||||
GDMonoUtils::runtime_object_init(mono_object, CACHED_CLASS(StringName));
|
||||
|
||||
CACHED_FIELD(StringName, ptr)->set_value_raw(mono_object, memnew(StringName(p_from)));
|
||||
|
||||
return mono_object;
|
||||
}
|
||||
|
||||
MonoObject *create_managed_from(const NodePath &p_from) {
|
||||
MonoObject *mono_object = mono_object_new(mono_domain_get(), CACHED_CLASS_RAW(NodePath));
|
||||
ERR_FAIL_NULL_V(mono_object, nullptr);
|
||||
|
||||
// Construct
|
||||
GDMonoUtils::runtime_object_init(mono_object, CACHED_CLASS(NodePath));
|
||||
|
||||
CACHED_FIELD(NodePath, ptr)->set_value_raw(mono_object, memnew(NodePath(p_from)));
|
||||
|
||||
return mono_object;
|
||||
}
|
||||
|
||||
MonoObject *create_managed_from(const RID &p_from) {
|
||||
MonoObject *mono_object = mono_object_new(mono_domain_get(), CACHED_CLASS_RAW(RID));
|
||||
ERR_FAIL_NULL_V(mono_object, nullptr);
|
||||
|
||||
// Construct
|
||||
GDMonoUtils::runtime_object_init(mono_object, CACHED_CLASS(RID));
|
||||
|
||||
CACHED_FIELD(RID, ptr)->set_value_raw(mono_object, memnew(RID(p_from)));
|
||||
|
||||
return mono_object;
|
||||
}
|
||||
|
||||
MonoObject *create_managed_from(const Array &p_from, GDMonoClass *p_class) {
|
||||
MonoObject *mono_object = mono_object_new(mono_domain_get(), p_class->get_mono_ptr());
|
||||
ERR_FAIL_NULL_V(mono_object, nullptr);
|
||||
|
||||
// Search constructor that takes a pointer as parameter
|
||||
MonoMethod *m;
|
||||
void *iter = nullptr;
|
||||
while ((m = mono_class_get_methods(p_class->get_mono_ptr(), &iter))) {
|
||||
if (strcmp(mono_method_get_name(m), ".ctor") == 0) {
|
||||
MonoMethodSignature *sig = mono_method_signature(m);
|
||||
void *front = nullptr;
|
||||
if (mono_signature_get_param_count(sig) == 1 &&
|
||||
mono_class_from_mono_type(mono_signature_get_params(sig, &front)) == CACHED_CLASS(IntPtr)->get_mono_ptr()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CRASH_COND(m == nullptr);
|
||||
|
||||
Array *new_array = memnew(Array(p_from));
|
||||
void *args[1] = { &new_array };
|
||||
|
||||
MonoException *exc = nullptr;
|
||||
GDMonoUtils::runtime_invoke(m, mono_object, args, &exc);
|
||||
UNHANDLED_EXCEPTION(exc);
|
||||
|
||||
return mono_object;
|
||||
}
|
||||
|
||||
MonoObject *create_managed_from(const Dictionary &p_from, GDMonoClass *p_class) {
|
||||
MonoObject *mono_object = mono_object_new(mono_domain_get(), p_class->get_mono_ptr());
|
||||
ERR_FAIL_NULL_V(mono_object, nullptr);
|
||||
|
||||
// Search constructor that takes a pointer as parameter
|
||||
MonoMethod *m;
|
||||
void *iter = nullptr;
|
||||
while ((m = mono_class_get_methods(p_class->get_mono_ptr(), &iter))) {
|
||||
if (strcmp(mono_method_get_name(m), ".ctor") == 0) {
|
||||
MonoMethodSignature *sig = mono_method_signature(m);
|
||||
void *front = nullptr;
|
||||
if (mono_signature_get_param_count(sig) == 1 &&
|
||||
mono_class_from_mono_type(mono_signature_get_params(sig, &front)) == CACHED_CLASS(IntPtr)->get_mono_ptr()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CRASH_COND(m == nullptr);
|
||||
|
||||
Dictionary *new_dict = memnew(Dictionary(p_from));
|
||||
void *args[1] = { &new_dict };
|
||||
|
||||
MonoException *exc = nullptr;
|
||||
GDMonoUtils::runtime_invoke(m, mono_object, args, &exc);
|
||||
UNHANDLED_EXCEPTION(exc);
|
||||
|
||||
return mono_object;
|
||||
}
|
||||
|
||||
MonoDomain *create_domain(const String &p_friendly_name) {
|
||||
print_verbose("Mono: Creating domain '" + p_friendly_name + "'...");
|
||||
|
||||
|
@ -487,6 +384,13 @@ MonoObject *runtime_invoke(MonoMethod *p_method, void *p_obj, void **p_params, M
|
|||
return ret;
|
||||
}
|
||||
|
||||
MonoObject *runtime_invoke_array(MonoMethod *p_method, void *p_obj, MonoArray *p_params, MonoException **r_exc) {
|
||||
GD_MONO_BEGIN_RUNTIME_INVOKE;
|
||||
MonoObject *ret = mono_runtime_invoke_array(p_method, p_obj, p_params, (MonoObject **)r_exc);
|
||||
GD_MONO_END_RUNTIME_INVOKE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
MonoString *object_to_string(MonoObject *p_obj, MonoException **r_exc) {
|
||||
GD_MONO_BEGIN_RUNTIME_INVOKE;
|
||||
MonoString *ret = mono_object_to_string(p_obj, (MonoObject **)r_exc);
|
||||
|
@ -540,109 +444,6 @@ void dispose(MonoObject *p_mono_object, MonoException **r_exc) {
|
|||
CACHED_METHOD_THUNK(GodotObject, Dispose).invoke(p_mono_object, r_exc);
|
||||
}
|
||||
|
||||
namespace Marshal {
|
||||
|
||||
#ifdef MONO_GLUE_ENABLED
|
||||
#ifdef TOOLS_ENABLED
|
||||
#define NO_GLUE_RET(m_ret) \
|
||||
{ \
|
||||
if (!GDMonoCache::cached_data.godot_api_cache_updated) \
|
||||
return m_ret; \
|
||||
}
|
||||
#else
|
||||
#define NO_GLUE_RET(m_ret) \
|
||||
{}
|
||||
#endif
|
||||
#else
|
||||
#define NO_GLUE_RET(m_ret) \
|
||||
{ return m_ret; }
|
||||
#endif
|
||||
|
||||
bool type_is_generic_array(MonoReflectionType *p_reftype) {
|
||||
NO_GLUE_RET(false);
|
||||
MonoException *exc = nullptr;
|
||||
MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericArray).invoke(p_reftype, &exc);
|
||||
UNHANDLED_EXCEPTION(exc);
|
||||
return (bool)res;
|
||||
}
|
||||
|
||||
bool type_is_generic_dictionary(MonoReflectionType *p_reftype) {
|
||||
NO_GLUE_RET(false);
|
||||
MonoException *exc = nullptr;
|
||||
MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericDictionary).invoke(p_reftype, &exc);
|
||||
UNHANDLED_EXCEPTION(exc);
|
||||
return (bool)res;
|
||||
}
|
||||
|
||||
bool type_is_system_generic_list(MonoReflectionType *p_reftype) {
|
||||
NO_GLUE_RET(false);
|
||||
MonoException *exc = nullptr;
|
||||
MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, TypeIsSystemGenericList).invoke(p_reftype, &exc);
|
||||
UNHANDLED_EXCEPTION(exc);
|
||||
return (bool)res;
|
||||
}
|
||||
|
||||
bool type_is_system_generic_dictionary(MonoReflectionType *p_reftype) {
|
||||
NO_GLUE_RET(false);
|
||||
MonoException *exc = nullptr;
|
||||
MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, TypeIsSystemGenericDictionary).invoke(p_reftype, &exc);
|
||||
UNHANDLED_EXCEPTION(exc);
|
||||
return (bool)res;
|
||||
}
|
||||
|
||||
bool type_is_generic_ienumerable(MonoReflectionType *p_reftype) {
|
||||
NO_GLUE_RET(false);
|
||||
MonoException *exc = nullptr;
|
||||
MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericIEnumerable).invoke(p_reftype, &exc);
|
||||
UNHANDLED_EXCEPTION(exc);
|
||||
return (bool)res;
|
||||
}
|
||||
|
||||
bool type_is_generic_icollection(MonoReflectionType *p_reftype) {
|
||||
NO_GLUE_RET(false);
|
||||
MonoException *exc = nullptr;
|
||||
MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericICollection).invoke(p_reftype, &exc);
|
||||
UNHANDLED_EXCEPTION(exc);
|
||||
return (bool)res;
|
||||
}
|
||||
|
||||
bool type_is_generic_idictionary(MonoReflectionType *p_reftype) {
|
||||
NO_GLUE_RET(false);
|
||||
MonoException *exc = nullptr;
|
||||
MonoBoolean res = CACHED_METHOD_THUNK(MarshalUtils, TypeIsGenericIDictionary).invoke(p_reftype, &exc);
|
||||
UNHANDLED_EXCEPTION(exc);
|
||||
return (bool)res;
|
||||
}
|
||||
|
||||
void array_get_element_type(MonoReflectionType *p_array_reftype, MonoReflectionType **r_elem_reftype) {
|
||||
MonoException *exc = nullptr;
|
||||
CACHED_METHOD_THUNK(MarshalUtils, ArrayGetElementType).invoke(p_array_reftype, r_elem_reftype, &exc);
|
||||
UNHANDLED_EXCEPTION(exc);
|
||||
}
|
||||
|
||||
void dictionary_get_key_value_types(MonoReflectionType *p_dict_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype) {
|
||||
MonoException *exc = nullptr;
|
||||
CACHED_METHOD_THUNK(MarshalUtils, DictionaryGetKeyValueTypes).invoke(p_dict_reftype, r_key_reftype, r_value_reftype, &exc);
|
||||
UNHANDLED_EXCEPTION(exc);
|
||||
}
|
||||
|
||||
GDMonoClass *make_generic_array_type(MonoReflectionType *p_elem_reftype) {
|
||||
NO_GLUE_RET(nullptr);
|
||||
MonoException *exc = nullptr;
|
||||
MonoReflectionType *reftype = CACHED_METHOD_THUNK(MarshalUtils, MakeGenericArrayType).invoke(p_elem_reftype, &exc);
|
||||
UNHANDLED_EXCEPTION(exc);
|
||||
return GDMono::get_singleton()->get_class(mono_class_from_mono_type(mono_reflection_type_get_type(reftype)));
|
||||
}
|
||||
|
||||
GDMonoClass *make_generic_dictionary_type(MonoReflectionType *p_key_reftype, MonoReflectionType *p_value_reftype) {
|
||||
NO_GLUE_RET(nullptr);
|
||||
MonoException *exc = nullptr;
|
||||
MonoReflectionType *reftype = CACHED_METHOD_THUNK(MarshalUtils, MakeGenericDictionaryType).invoke(p_key_reftype, p_value_reftype, &exc);
|
||||
UNHANDLED_EXCEPTION(exc);
|
||||
return GDMono::get_singleton()->get_class(mono_class_from_mono_type(mono_reflection_type_get_type(reftype)));
|
||||
}
|
||||
} // namespace Marshal
|
||||
|
||||
ScopeThreadAttach::ScopeThreadAttach() {
|
||||
if (likely(GDMono::get_singleton()->is_runtime_initialized()) && unlikely(!mono_domain_get())) {
|
||||
mono_thread = GDMonoUtils::attach_current_thread();
|
||||
|
@ -657,7 +458,6 @@ ScopeThreadAttach::~ScopeThreadAttach() {
|
|||
|
||||
StringName get_native_godot_class_name(GDMonoClass *p_class) {
|
||||
MonoObject *native_name_obj = p_class->get_field(BINDINGS_NATIVE_NAME_FIELD)->get_value(nullptr);
|
||||
StringName *ptr = GDMonoMarshal::unbox<StringName *>(CACHED_FIELD(StringName, ptr)->get_value(native_name_obj));
|
||||
return ptr ? *ptr : StringName();
|
||||
return (StringName)GDMonoMarshal::mono_object_to_variant(native_name_obj);
|
||||
}
|
||||
} // namespace GDMonoUtils
|
||||
|
|
|
@ -52,23 +52,6 @@
|
|||
|
||||
namespace GDMonoUtils {
|
||||
|
||||
namespace Marshal {
|
||||
|
||||
bool type_is_generic_array(MonoReflectionType *p_reftype);
|
||||
bool type_is_generic_dictionary(MonoReflectionType *p_reftype);
|
||||
bool type_is_system_generic_list(MonoReflectionType *p_reftype);
|
||||
bool type_is_system_generic_dictionary(MonoReflectionType *p_reftype);
|
||||
bool type_is_generic_ienumerable(MonoReflectionType *p_reftype);
|
||||
bool type_is_generic_icollection(MonoReflectionType *p_reftype);
|
||||
bool type_is_generic_idictionary(MonoReflectionType *p_reftype);
|
||||
|
||||
void array_get_element_type(MonoReflectionType *p_array_reftype, MonoReflectionType **r_elem_reftype);
|
||||
void dictionary_get_key_value_types(MonoReflectionType *p_dict_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype);
|
||||
|
||||
GDMonoClass *make_generic_array_type(MonoReflectionType *p_elem_reftype);
|
||||
GDMonoClass *make_generic_dictionary_type(MonoReflectionType *p_key_reftype, MonoReflectionType *p_value_reftype);
|
||||
} // namespace Marshal
|
||||
|
||||
_FORCE_INLINE_ void hash_combine(uint32_t &p_hash, const uint32_t &p_with_hash) {
|
||||
p_hash ^= p_with_hash + 0x9e3779b9 + (p_hash << 6) + (p_hash >> 2);
|
||||
}
|
||||
|
@ -94,20 +77,12 @@ void free_gchandle(uint32_t p_gchandle);
|
|||
|
||||
void runtime_object_init(MonoObject *p_this_obj, GDMonoClass *p_class, MonoException **r_exc = nullptr);
|
||||
|
||||
bool mono_delegate_equal(MonoDelegate *p_a, MonoDelegate *p_b);
|
||||
|
||||
GDMonoClass *get_object_class(MonoObject *p_object);
|
||||
GDMonoClass *type_get_proxy_class(const StringName &p_type);
|
||||
GDMonoClass *get_class_native_base(GDMonoClass *p_class);
|
||||
|
||||
MonoObject *create_managed_for_godot_object(GDMonoClass *p_class, const StringName &p_native, Object *p_object);
|
||||
|
||||
MonoObject *create_managed_from(const StringName &p_from);
|
||||
MonoObject *create_managed_from(const NodePath &p_from);
|
||||
MonoObject *create_managed_from(const RID &p_from);
|
||||
MonoObject *create_managed_from(const Array &p_from, GDMonoClass *p_class);
|
||||
MonoObject *create_managed_from(const Dictionary &p_from, GDMonoClass *p_class);
|
||||
|
||||
MonoDomain *create_domain(const String &p_friendly_name);
|
||||
|
||||
String get_type_desc(MonoType *p_type);
|
||||
|
@ -138,6 +113,7 @@ _FORCE_INLINE_ int &get_runtime_invoke_count_ref() {
|
|||
}
|
||||
|
||||
MonoObject *runtime_invoke(MonoMethod *p_method, void *p_obj, void **p_params, MonoException **r_exc);
|
||||
MonoObject *runtime_invoke_array(MonoMethod *p_method, void *p_obj, MonoArray *p_params, MonoException **r_exc);
|
||||
|
||||
MonoString *object_to_string(MonoObject *p_obj, MonoException **r_exc);
|
||||
|
||||
|
|
|
@ -92,6 +92,10 @@ ObjectID SignalAwaiterCallable::get_object() const {
|
|||
return target_id;
|
||||
}
|
||||
|
||||
StringName SignalAwaiterCallable::get_signal() const {
|
||||
return signal;
|
||||
}
|
||||
|
||||
void SignalAwaiterCallable::call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const {
|
||||
r_call_error.error = Callable::CallError::CALL_ERROR_INVALID_METHOD; // Can't find anything better
|
||||
r_return_value = Variant();
|
||||
|
|
|
@ -38,7 +38,12 @@
|
|||
|
||||
Error gd_mono_connect_signal_awaiter(Object *p_source, const StringName &p_signal, Object *p_target, MonoObject *p_awaiter);
|
||||
|
||||
class SignalAwaiterCallable : public CallableCustom {
|
||||
class BaseSignalCallable : public CallableCustom {
|
||||
public:
|
||||
virtual StringName get_signal() const = 0;
|
||||
};
|
||||
|
||||
class SignalAwaiterCallable : public BaseSignalCallable {
|
||||
ObjectID target_id;
|
||||
MonoGCHandleData awaiter_handle;
|
||||
StringName signal;
|
||||
|
@ -59,7 +64,7 @@ public:
|
|||
|
||||
ObjectID get_object() const override;
|
||||
|
||||
_FORCE_INLINE_ StringName get_signal() const { return signal; }
|
||||
StringName get_signal() const override;
|
||||
|
||||
void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
|
||||
|
||||
|
@ -67,7 +72,7 @@ public:
|
|||
~SignalAwaiterCallable();
|
||||
};
|
||||
|
||||
class EventSignalCallable : public CallableCustom {
|
||||
class EventSignalCallable : public BaseSignalCallable {
|
||||
Object *owner;
|
||||
const CSharpScript::EventSignal *event_signal;
|
||||
|
||||
|
@ -87,7 +92,7 @@ public:
|
|||
|
||||
ObjectID get_object() const override;
|
||||
|
||||
StringName get_signal() const;
|
||||
StringName get_signal() const override;
|
||||
|
||||
void call(const Variant **p_arguments, int p_argcount, Variant &r_return_value, Callable::CallError &r_call_error) const override;
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ int sfind(const String &p_text, int p_from) {
|
|||
break;
|
||||
case 1: {
|
||||
char32_t c = src[read_pos];
|
||||
found = src[read_pos] == 's' || (c >= '0' && c <= '4');
|
||||
found = src[read_pos] == 's' || (c >= '0' && c <= '5');
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -86,32 +86,13 @@ int sfind(const String &p_text, int p_from) {
|
|||
}
|
||||
} // namespace
|
||||
|
||||
String sformat(const String &p_text, const Variant &p1, const Variant &p2, const Variant &p3, const Variant &p4, const Variant &p5) {
|
||||
String sformat(const String &p_text, const String &p1, const String &p2,
|
||||
const String &p3, const String &p4, const String &p5, const String &p6) {
|
||||
if (p_text.length() < 2) {
|
||||
return p_text;
|
||||
}
|
||||
|
||||
Array args;
|
||||
|
||||
if (p1.get_type() != Variant::NIL) {
|
||||
args.push_back(p1);
|
||||
|
||||
if (p2.get_type() != Variant::NIL) {
|
||||
args.push_back(p2);
|
||||
|
||||
if (p3.get_type() != Variant::NIL) {
|
||||
args.push_back(p3);
|
||||
|
||||
if (p4.get_type() != Variant::NIL) {
|
||||
args.push_back(p4);
|
||||
|
||||
if (p5.get_type() != Variant::NIL) {
|
||||
args.push_back(p5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
String args[6] = { p1, p2, p3, p4, p5, p6 };
|
||||
|
||||
String new_string;
|
||||
|
||||
|
@ -125,7 +106,7 @@ String sformat(const String &p_text, const Variant &p1, const Variant &p2, const
|
|||
int req_index = (c == 's' ? findex++ : c - '0');
|
||||
|
||||
new_string += p_text.substr(search_from, result - search_from);
|
||||
new_string += args[req_index].operator String();
|
||||
new_string += args[req_index];
|
||||
search_from = result + 2;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,8 @@
|
|||
|
||||
#include <stdarg.h>
|
||||
|
||||
String sformat(const String &p_text, const Variant &p1 = Variant(), const Variant &p2 = Variant(), const Variant &p3 = Variant(), const Variant &p4 = Variant(), const Variant &p5 = Variant());
|
||||
String sformat(const String &p_text, const String &p1 = String(), const String &p2 = String(),
|
||||
const String &p3 = String(), const String &p4 = String(), const String &p5 = String(), const String &p6 = String());
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
bool is_csharp_keyword(const String &p_name);
|
||||
|
|
Loading…
Reference in a new issue