Compare commits
9 commits
Author | SHA1 | Date | |
---|---|---|---|
ca0ce5b46e | |||
3388d68dff | |||
50b603c7dc | |||
f744d99179 | |||
3f1a620102 | |||
bbde1b1f09 | |||
66a89c7925 | |||
f580b1efdc | |||
483071716e |
34
.github/workflows/linux_builds.yml
vendored
34
.github/workflows/linux_builds.yml
vendored
|
@ -12,6 +12,10 @@ jobs:
|
|||
runs-on: "ubuntu-20.04"
|
||||
name: Editor (target=release_debug, tools=yes, tests=yes)
|
||||
|
||||
env:
|
||||
DOTNET_NOLOGO: true
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
|
@ -58,18 +62,31 @@ jobs:
|
|||
python --version
|
||||
scons --version
|
||||
|
||||
- name: Set up .NET Sdk
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: '5.0.x'
|
||||
|
||||
# We should always be explicit with our flags usage here since it's gonna be sure to always set those flags
|
||||
- name: Compilation
|
||||
env:
|
||||
SCONS_CACHE: ${{github.workspace}}/.scons_cache/
|
||||
run: |
|
||||
scons tools=yes tests=yes target=release_debug
|
||||
scons tools=yes tests=yes target=release_debug module_mono_enabled=yes
|
||||
ls -l bin/
|
||||
|
||||
- name: Generate C# glue
|
||||
run: |
|
||||
./bin/godot.linuxbsd.opt.tools.64.mono --generate-mono-glue ./modules/mono/glue
|
||||
|
||||
- name: Build .NET solutions
|
||||
run: |
|
||||
./modules/mono/build_scripts/build_assemblies.py --godot-output-dir=./bin --godot-target=release_debug --godot-platform=linuxbsd
|
||||
|
||||
# Execute unit tests for the editor
|
||||
- name: Unit Tests
|
||||
run: |
|
||||
./bin/godot.linuxbsd.opt.tools.64 --test
|
||||
./bin/godot.linuxbsd.opt.tools.64.mono --test
|
||||
|
||||
# Download, unzip and setup SwiftShader library [4466040]
|
||||
- name: Download SwiftShader
|
||||
|
@ -85,7 +102,7 @@ jobs:
|
|||
run: |
|
||||
echo "Running --doctool to see if this changes the public API without updating the documentation."
|
||||
echo -e "If a diff is shown, it means that your code/doc changes are incomplete and you should update the class reference with --doctool.\n\n"
|
||||
VK_ICD_FILENAMES=$(pwd)/vk_swiftshader_icd.json DRI_PRIME=0 xvfb-run bin/godot.linuxbsd.opt.tools.64 --doctool . 2>&1 > /dev/null || true
|
||||
VK_ICD_FILENAMES=$(pwd)/vk_swiftshader_icd.json DRI_PRIME=0 xvfb-run bin/godot.linuxbsd.opt.tools.64.mono --doctool . 2>&1 > /dev/null || true
|
||||
git diff --color --exit-code && ! git ls-files --others --exclude-standard | sed -e 's/^/New doc file missing in PR: /' | grep 'xml$'
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
|
@ -190,6 +207,10 @@ jobs:
|
|||
runs-on: "ubuntu-20.04"
|
||||
name: Template w/ Mono (target=release, tools=no)
|
||||
|
||||
env:
|
||||
DOTNET_NOLOGO: true
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
|
@ -236,11 +257,16 @@ jobs:
|
|||
python --version
|
||||
scons --version
|
||||
|
||||
- name: Set up .NET Sdk
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: '5.0.x'
|
||||
|
||||
- name: Compilation
|
||||
env:
|
||||
SCONS_CACHE: ${{github.workspace}}/.scons_cache/
|
||||
run: |
|
||||
scons target=release tools=no module_mono_enabled=yes mono_glue=no
|
||||
scons target=release tools=no module_mono_enabled=yes
|
||||
ls -l bin/
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
|
|
|
@ -1293,20 +1293,6 @@
|
|||
<member name="memory/limits/multithreaded_server/rid_pool_prealloc" type="int" setter="" getter="" default="60">
|
||||
This is used by servers when used in multi-threading mode (servers and visual). RIDs are preallocated to avoid stalling the server requesting them on threads. If servers get stalled too often when loading resources in a thread, increase this number.
|
||||
</member>
|
||||
<member name="mono/debugger_agent/port" type="int" setter="" getter="" default="23685">
|
||||
</member>
|
||||
<member name="mono/debugger_agent/wait_for_debugger" type="bool" setter="" getter="" default="false">
|
||||
</member>
|
||||
<member name="mono/debugger_agent/wait_timeout" type="int" setter="" getter="" default="3000">
|
||||
</member>
|
||||
<member name="mono/profiler/args" type="String" setter="" getter="" default=""log:calls,alloc,sample,output=output.mlpd"">
|
||||
</member>
|
||||
<member name="mono/profiler/enabled" type="bool" setter="" getter="" default="false">
|
||||
</member>
|
||||
<member name="mono/project/auto_update_project" type="bool" setter="" getter="" default="true">
|
||||
</member>
|
||||
<member name="mono/unhandled_exception_policy" type="int" setter="" getter="" default="0">
|
||||
</member>
|
||||
<member name="navigation/2d/default_cell_size" type="int" setter="" getter="" default="10">
|
||||
Default cell size for 2D navigation maps. See [method NavigationServer2D.map_set_cell_size].
|
||||
</member>
|
||||
|
|
|
@ -1944,20 +1944,6 @@ bool Main::start() {
|
|||
ERR_FAIL_COND_V_MSG(!da, false, "Argument supplied to --doctool must be a valid directory path.");
|
||||
}
|
||||
|
||||
#ifndef MODULE_MONO_ENABLED
|
||||
// Hack to define Mono-specific project settings even on non-Mono builds,
|
||||
// so that we don't lose their descriptions and default values in DocData.
|
||||
// Default values should be synced with mono_gd/gd_mono.cpp.
|
||||
GLOBAL_DEF("mono/debugger_agent/port", 23685);
|
||||
GLOBAL_DEF("mono/debugger_agent/wait_for_debugger", false);
|
||||
GLOBAL_DEF("mono/debugger_agent/wait_timeout", 3000);
|
||||
GLOBAL_DEF("mono/profiler/args", "log:calls,alloc,sample,output=output.mlpd");
|
||||
GLOBAL_DEF("mono/profiler/enabled", false);
|
||||
GLOBAL_DEF("mono/unhandled_exception_policy", 0);
|
||||
// From editor/csharp_project.cpp.
|
||||
GLOBAL_DEF("mono/project/auto_update_project", true);
|
||||
#endif
|
||||
|
||||
DocTools doc;
|
||||
doc.generate(doc_base);
|
||||
|
||||
|
|
|
@ -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
|
307
modules/mono/build_scripts/build_assemblies.py
Executable file
307
modules/mono/build_scripts/build_assemblies.py
Executable file
|
@ -0,0 +1,307 @@
|
|||
#!/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",
|
||||
"GodotPlugins.dll",
|
||||
"GodotPlugins.pdb",
|
||||
"GodotPlugins.runtimeconfig.json",
|
||||
]
|
||||
|
||||
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))
|
||||
plugins_src_dir = os.path.abspath(os.path.join(sln, os.pardir, "GodotPlugins", "bin", build_config, "net5.0"))
|
||||
|
||||
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)
|
||||
if not os.path.isfile(src_path):
|
||||
src_path = os.path.join(plugins_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,53 +0,0 @@
|
|||
def generate_compressed_config(config_src, output_dir):
|
||||
import os.path
|
||||
|
||||
# Source file
|
||||
with open(os.path.join(output_dir, "android_mono_config.gen.cpp"), "w") as cpp:
|
||||
with open(config_src, "rb") as f:
|
||||
buf = f.read()
|
||||
decompr_size = len(buf)
|
||||
import zlib
|
||||
|
||||
buf = zlib.compress(buf)
|
||||
compr_size = len(buf)
|
||||
|
||||
bytes_seq_str = ""
|
||||
for i, buf_idx in enumerate(range(compr_size)):
|
||||
if i > 0:
|
||||
bytes_seq_str += ", "
|
||||
bytes_seq_str += str(buf[buf_idx])
|
||||
|
||||
cpp.write(
|
||||
"""/* THIS FILE IS GENERATED DO NOT EDIT */
|
||||
#include "android_mono_config.h"
|
||||
|
||||
#ifdef ANDROID_ENABLED
|
||||
|
||||
#include "core/io/compression.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
// config
|
||||
static const int config_compressed_size = %d;
|
||||
static const int config_uncompressed_size = %d;
|
||||
static const unsigned char config_compressed_data[] = { %s };
|
||||
} // namespace
|
||||
|
||||
String get_godot_android_mono_config() {
|
||||
Vector<uint8_t> data;
|
||||
data.resize(config_uncompressed_size);
|
||||
uint8_t* w = data.ptrw();
|
||||
Compression::decompress(w, config_uncompressed_size, config_compressed_data,
|
||||
config_compressed_size, Compression::MODE_DEFLATE);
|
||||
String s;
|
||||
if (s.parse_utf8((const char *)w, data.size())) {
|
||||
ERR_FAIL_V(String());
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif // ANDROID_ENABLED
|
||||
"""
|
||||
% (compr_size, decompr_size, bytes_seq_str)
|
||||
)
|
|
@ -1,28 +0,0 @@
|
|||
<configuration>
|
||||
<dllmap wordsize="32" dll="i:cygwin1.dll" target="/system/lib/libc.so" />
|
||||
<dllmap wordsize="64" dll="i:cygwin1.dll" target="/system/lib64/libc.so" />
|
||||
<dllmap wordsize="32" dll="libc" target="/system/lib/libc.so" />
|
||||
<dllmap wordsize="64" dll="libc" target="/system/lib64/libc.so" />
|
||||
<dllmap wordsize="32" dll="intl" target="/system/lib/libc.so" />
|
||||
<dllmap wordsize="64" dll="intl" target="/system/lib64/libc.so" />
|
||||
<dllmap wordsize="32" dll="libintl" target="/system/lib/libc.so" />
|
||||
<dllmap wordsize="64" dll="libintl" target="/system/lib64/libc.so" />
|
||||
<dllmap dll="MonoPosixHelper" target="libMonoPosixHelper.so" />
|
||||
<dllmap dll="System.Native" target="libmono-native.so" />
|
||||
<dllmap wordsize="32" dll="i:msvcrt" target="/system/lib/libc.so" />
|
||||
<dllmap wordsize="64" dll="i:msvcrt" target="/system/lib64/libc.so" />
|
||||
<dllmap wordsize="32" dll="i:msvcrt.dll" target="/system/lib/libc.so" />
|
||||
<dllmap wordsize="64" dll="i:msvcrt.dll" target="/system/lib64/libc.so" />
|
||||
<dllmap wordsize="32" dll="sqlite" target="/system/lib/libsqlite.so" />
|
||||
<dllmap wordsize="64" dll="sqlite" target="/system/lib64/libsqlite.so" />
|
||||
<dllmap wordsize="32" dll="sqlite3" target="/system/lib/libsqlite.so" />
|
||||
<dllmap wordsize="64" dll="sqlite3" target="/system/lib64/libsqlite.so" />
|
||||
<dllmap wordsize="32" dll="liblog" target="/system/lib/liblog.so" />
|
||||
<dllmap wordsize="64" dll="liblog" target="/system/lib64/liblog.so" />
|
||||
<dllmap dll="i:kernel32.dll">
|
||||
<dllentry dll="__Internal" name="CopyMemory" target="mono_win32_compat_CopyMemory"/>
|
||||
<dllentry dll="__Internal" name="FillMemory" target="mono_win32_compat_FillMemory"/>
|
||||
<dllentry dll="__Internal" name="MoveMemory" target="mono_win32_compat_MoveMemory"/>
|
||||
<dllentry dll="__Internal" name="ZeroMemory" target="mono_win32_compat_ZeroMemory"/>
|
||||
</dllmap>
|
||||
</configuration>
|
|
@ -1,65 +1,5 @@
|
|||
import os
|
||||
import os.path
|
||||
import subprocess
|
||||
|
||||
from SCons.Script import Dir, Environment
|
||||
|
||||
if os.name == "nt":
|
||||
from . import mono_reg_utils as monoreg
|
||||
|
||||
|
||||
android_arch_dirs = {
|
||||
"armv7": "armeabi-v7a",
|
||||
"arm64v8": "arm64-v8a",
|
||||
"x86": "x86",
|
||||
"x86_64": "x86_64",
|
||||
}
|
||||
|
||||
|
||||
def get_android_out_dir(env):
|
||||
return os.path.join(
|
||||
Dir("#platform/android/java/lib/libs").abspath,
|
||||
"release" if env["target"] == "release" else "debug",
|
||||
android_arch_dirs[env["android_arch"]],
|
||||
)
|
||||
|
||||
|
||||
def find_name_in_dir_files(directory, names, prefixes=[""], extensions=[""]):
|
||||
for extension in extensions:
|
||||
if extension and not extension.startswith("."):
|
||||
extension = "." + extension
|
||||
for prefix in prefixes:
|
||||
for curname in names:
|
||||
if os.path.isfile(os.path.join(directory, prefix + curname + extension)):
|
||||
return curname
|
||||
return ""
|
||||
|
||||
|
||||
def find_file_in_dir(directory, names, prefixes=[""], extensions=[""]):
|
||||
for extension in extensions:
|
||||
if extension and not extension.startswith("."):
|
||||
extension = "." + extension
|
||||
for prefix in prefixes:
|
||||
for curname in names:
|
||||
filename = prefix + curname + extension
|
||||
if os.path.isfile(os.path.join(directory, filename)):
|
||||
return filename
|
||||
return ""
|
||||
|
||||
|
||||
def copy_file(src_dir, dst_dir, src_name, dst_name=""):
|
||||
from shutil import copy
|
||||
|
||||
src_path = os.path.join(Dir(src_dir).abspath, src_name)
|
||||
dst_dir = Dir(dst_dir).abspath
|
||||
|
||||
if not os.path.isdir(dst_dir):
|
||||
os.makedirs(dst_dir)
|
||||
|
||||
if dst_name:
|
||||
copy(src_path, os.path.join(dst_dir, dst_name))
|
||||
else:
|
||||
copy(src_path, dst_dir)
|
||||
|
||||
|
||||
def is_desktop(platform):
|
||||
|
@ -71,504 +11,162 @@ def is_unix_like(platform):
|
|||
|
||||
|
||||
def module_supports_tools_on(platform):
|
||||
return platform not in ["android", "javascript", "iphone"]
|
||||
|
||||
|
||||
def find_wasm_src_dir(mono_root):
|
||||
hint_dirs = [
|
||||
os.path.join(mono_root, "src"),
|
||||
os.path.join(mono_root, "../src"),
|
||||
]
|
||||
for hint_dir in hint_dirs:
|
||||
if os.path.isfile(os.path.join(hint_dir, "driver.c")):
|
||||
return hint_dir
|
||||
return ""
|
||||
return is_desktop(platform)
|
||||
|
||||
|
||||
def configure(env, env_mono):
|
||||
bits = env["bits"]
|
||||
is_android = env["platform"] == "android"
|
||||
is_javascript = env["platform"] == "javascript"
|
||||
is_ios = env["platform"] == "iphone"
|
||||
is_ios_sim = is_ios and env["arch"] in ["x86", "x86_64"]
|
||||
# is_android = env["platform"] == "android"
|
||||
# is_javascript = env["platform"] == "javascript"
|
||||
# is_ios = env["platform"] == "iphone"
|
||||
# is_ios_sim = is_ios and env["arch"] in ["x86", "x86_64"]
|
||||
|
||||
tools_enabled = env["tools"]
|
||||
mono_static = env["mono_static"]
|
||||
copy_mono_root = env["copy_mono_root"]
|
||||
|
||||
mono_prefix = env["mono_prefix"]
|
||||
mono_bcl = env["mono_bcl"]
|
||||
|
||||
mono_lib_names = ["mono-2.0-sgen", "monosgen-2.0"]
|
||||
|
||||
if is_android and not env["android_arch"] in android_arch_dirs:
|
||||
raise RuntimeError("This module does not support the specified 'android_arch': " + env["android_arch"])
|
||||
|
||||
if tools_enabled and not module_supports_tools_on(env["platform"]):
|
||||
# TODO:
|
||||
# Android: We have to add the data directory to the apk, concretely the Api and Tools folders.
|
||||
raise RuntimeError("This module does not currently support building for this platform with tools enabled")
|
||||
|
||||
if is_android and mono_static:
|
||||
# FIXME: When static linking and doing something that requires libmono-native, we get a dlopen error as 'libmono-native'
|
||||
# seems to depend on 'libmonosgen-2.0'. Could be fixed by re-directing to '__Internal' with a dllmap or in the dlopen hook.
|
||||
raise RuntimeError("Statically linking Mono is not currently supported for this platform")
|
||||
|
||||
if not mono_static and (is_javascript or is_ios):
|
||||
raise RuntimeError("Dynamically linking Mono is not currently supported for this platform")
|
||||
|
||||
if not mono_prefix and (os.getenv("MONO32_PREFIX") or os.getenv("MONO64_PREFIX")):
|
||||
print(
|
||||
"WARNING: The environment variables 'MONO32_PREFIX' and 'MONO64_PREFIX' are deprecated; use the"
|
||||
" 'mono_prefix' SCons parameter instead"
|
||||
)
|
||||
|
||||
# Although we don't support building with tools for any platform where we currently use static AOT,
|
||||
# if these are supported in the future, we won't be using static AOT for them as that would be
|
||||
# too restrictive for the editor. These builds would probably be made to only use the interpreter.
|
||||
mono_aot_static = (is_ios and not is_ios_sim) and not env["tools"]
|
||||
|
||||
# Static AOT is only supported on the root domain
|
||||
mono_single_appdomain = mono_aot_static
|
||||
|
||||
if mono_single_appdomain:
|
||||
env_mono.Append(CPPDEFINES=["GD_MONO_SINGLE_APPDOMAIN"])
|
||||
|
||||
if (env["tools"] or env["target"] != "release") and not mono_single_appdomain:
|
||||
if env["tools"] or env["target"] != "release":
|
||||
env_mono.Append(CPPDEFINES=["GD_MONO_HOT_RELOAD"])
|
||||
|
||||
if env["platform"] == "windows":
|
||||
mono_root = mono_prefix
|
||||
dotnet_root = env["dotnet_root"]
|
||||
|
||||
if not mono_root and os.name == "nt":
|
||||
mono_root = monoreg.find_mono_root_dir(bits)
|
||||
if not dotnet_root:
|
||||
dotnet_exe = find_executable("dotnet")
|
||||
if dotnet_exe:
|
||||
dotnet_exe_realpath = os.path.realpath(dotnet_exe) # Eliminate symbolic links
|
||||
dotnet_root = os.path.abspath(os.path.join(dotnet_exe_realpath, os.pardir))
|
||||
else:
|
||||
raise RuntimeError("Cannot find .NET Core Sdk")
|
||||
|
||||
if not mono_root:
|
||||
raise RuntimeError(
|
||||
"Mono installation directory not found; specify one manually with the 'mono_prefix' SCons parameter"
|
||||
print("Found .NET Core Sdk root directory: " + dotnet_root)
|
||||
|
||||
dotnet_cmd = os.path.join(dotnet_root, "dotnet.exe" if os.name == "nt" else "dotnet")
|
||||
|
||||
runtime_identifier = determine_runtime_identifier(env)
|
||||
|
||||
# TODO: In the future, if it can't be found this way, we want to obtain it
|
||||
# from the runtime.{runtime_identifier}.Microsoft.NETCore.DotNetAppHost NuGet package.
|
||||
app_host_search_version = "5.0"
|
||||
app_host_version = find_app_host_version(dotnet_cmd, app_host_search_version)
|
||||
if not app_host_version:
|
||||
raise RuntimeError("Cannot find .NET app host for version: " + app_host_search_version)
|
||||
|
||||
app_host_dir = os.path.join(
|
||||
dotnet_root,
|
||||
"packs",
|
||||
"Microsoft.NETCore.App.Host." + runtime_identifier,
|
||||
app_host_version,
|
||||
"runtimes",
|
||||
runtime_identifier,
|
||||
"native",
|
||||
)
|
||||
|
||||
print("Found Mono root directory: " + mono_root)
|
||||
def check_app_host_file_exists(file):
|
||||
file_path = os.path.join(app_host_dir, file)
|
||||
if not os.path.isfile(file_path):
|
||||
raise RuntimeError("File not found: " + file_path)
|
||||
|
||||
mono_lib_path = os.path.join(mono_root, "lib")
|
||||
# TODO:
|
||||
# All libnethost does for us is provide a function to find hostfxr.
|
||||
# If we could handle that logic ourselves we could void linking it.
|
||||
|
||||
env.Append(LIBPATH=mono_lib_path)
|
||||
env_mono.Prepend(CPPPATH=os.path.join(mono_root, "include", "mono-2.0"))
|
||||
# nethost file names:
|
||||
# static: libnethost.a/lib
|
||||
# shared: libnethost.a/dylib and nethost.dll
|
||||
check_app_host_file_exists("libnethost.lib" if os.name == "nt" else "libnethost.a")
|
||||
check_app_host_file_exists("nethost.h")
|
||||
check_app_host_file_exists("hostfxr.h")
|
||||
check_app_host_file_exists("coreclr_delegates.h")
|
||||
|
||||
lib_suffixes = [".lib"]
|
||||
env.Append(LIBPATH=[app_host_dir])
|
||||
env_mono.Prepend(CPPPATH=app_host_dir)
|
||||
|
||||
if not env.msvc:
|
||||
# MingW supports both '.a' and '.lib'
|
||||
lib_suffixes.insert(0, ".a")
|
||||
libnethost_path = os.path.join(app_host_dir, "libnethost.lib" if os.name == "nt" else "libnethost.a")
|
||||
|
||||
if mono_static:
|
||||
if env["platform"] == "windows":
|
||||
if env.msvc:
|
||||
mono_static_lib_name = "libmono-static-sgen"
|
||||
env.Append(LINKFLAGS="libnethost.lib")
|
||||
else:
|
||||
mono_static_lib_name = "libmonosgen-2.0"
|
||||
|
||||
mono_static_lib_file = find_file_in_dir(mono_lib_path, [mono_static_lib_name], extensions=lib_suffixes)
|
||||
|
||||
if not mono_static_lib_file:
|
||||
raise RuntimeError("Could not find static mono library in: " + mono_lib_path)
|
||||
|
||||
if env.msvc:
|
||||
env.Append(LINKFLAGS=mono_static_lib_file)
|
||||
|
||||
env.Append(LINKFLAGS="Mincore.lib")
|
||||
env.Append(LINKFLAGS="msvcrt.lib")
|
||||
env.Append(LINKFLAGS="LIBCMT.lib")
|
||||
env.Append(LINKFLAGS="Psapi.lib")
|
||||
else:
|
||||
mono_static_lib_file_path = os.path.join(mono_lib_path, mono_static_lib_file)
|
||||
env.Append(LINKFLAGS=["-Wl,-whole-archive", mono_static_lib_file_path, "-Wl,-no-whole-archive"])
|
||||
|
||||
env.Append(LIBS=["psapi"])
|
||||
env.Append(LIBS=["version"])
|
||||
else:
|
||||
mono_lib_file = find_file_in_dir(mono_lib_path, mono_lib_names, extensions=lib_suffixes)
|
||||
|
||||
if not mono_lib_file:
|
||||
raise RuntimeError("Could not find mono library in: " + mono_lib_path)
|
||||
|
||||
if env.msvc:
|
||||
env.Append(LINKFLAGS=mono_lib_file)
|
||||
else:
|
||||
mono_lib_file_path = os.path.join(mono_lib_path, mono_lib_file)
|
||||
env.Append(LINKFLAGS=mono_lib_file_path)
|
||||
|
||||
mono_bin_path = os.path.join(mono_root, "bin")
|
||||
|
||||
mono_dll_file = find_file_in_dir(mono_bin_path, mono_lib_names, prefixes=["", "lib"], extensions=[".dll"])
|
||||
|
||||
if not mono_dll_file:
|
||||
raise RuntimeError("Could not find mono shared library in: " + mono_bin_path)
|
||||
|
||||
copy_file(mono_bin_path, "#bin", mono_dll_file)
|
||||
env.Append(LINKFLAGS=["-Wl,-whole-archive", libnethost_path, "-Wl,-no-whole-archive"])
|
||||
else:
|
||||
is_apple = env["platform"] in ["osx", "iphone"]
|
||||
is_macos = is_apple and not is_ios
|
||||
# is_macos = is_apple and not is_ios
|
||||
|
||||
sharedlib_ext = ".dylib" if is_apple else ".so"
|
||||
|
||||
mono_root = mono_prefix
|
||||
mono_lib_path = ""
|
||||
mono_so_file = ""
|
||||
|
||||
if not mono_root and (is_android or is_javascript or is_ios):
|
||||
raise RuntimeError(
|
||||
"Mono installation directory not found; specify one manually with the 'mono_prefix' SCons parameter"
|
||||
)
|
||||
|
||||
if not mono_root and is_macos:
|
||||
# Try with some known directories under OSX
|
||||
hint_dirs = ["/Library/Frameworks/Mono.framework/Versions/Current", "/usr/local/var/homebrew/linked/mono"]
|
||||
for hint_dir in hint_dirs:
|
||||
if os.path.isdir(hint_dir):
|
||||
mono_root = hint_dir
|
||||
break
|
||||
|
||||
# We can't use pkg-config to link mono statically,
|
||||
# but we can still use it to find the mono root directory
|
||||
if not mono_root and mono_static:
|
||||
mono_root = pkgconfig_try_find_mono_root(mono_lib_names, sharedlib_ext)
|
||||
if not mono_root:
|
||||
raise RuntimeError(
|
||||
"Building with mono_static=yes, but failed to find the mono prefix with pkg-config; "
|
||||
+ "specify one manually with the 'mono_prefix' SCons parameter"
|
||||
)
|
||||
|
||||
if is_ios and not is_ios_sim:
|
||||
env_mono.Append(CPPDEFINES=["IOS_DEVICE"])
|
||||
|
||||
if mono_root:
|
||||
print("Found Mono root directory: " + mono_root)
|
||||
|
||||
mono_lib_path = os.path.join(mono_root, "lib")
|
||||
|
||||
env.Append(LIBPATH=[mono_lib_path])
|
||||
env_mono.Prepend(CPPPATH=os.path.join(mono_root, "include", "mono-2.0"))
|
||||
|
||||
mono_lib = find_name_in_dir_files(mono_lib_path, mono_lib_names, prefixes=["lib"], extensions=[".a"])
|
||||
|
||||
if not mono_lib:
|
||||
raise RuntimeError("Could not find mono library in: " + mono_lib_path)
|
||||
|
||||
env_mono.Append(CPPDEFINES=["_REENTRANT"])
|
||||
|
||||
if mono_static:
|
||||
if not is_javascript:
|
||||
env.Append(LINKFLAGS=["-rdynamic"])
|
||||
|
||||
mono_lib_file = os.path.join(mono_lib_path, "lib" + mono_lib + ".a")
|
||||
# if is_ios and not is_ios_sim:
|
||||
# env_mono.Append(CPPDEFINES=["IOS_DEVICE"])
|
||||
|
||||
if is_apple:
|
||||
if is_macos:
|
||||
env.Append(LINKFLAGS=["-Wl,-force_load," + mono_lib_file])
|
||||
env.Append(LINKFLAGS=["-Wl,-force_load," + libnethost_path])
|
||||
else:
|
||||
arch = env["arch"]
|
||||
|
||||
def copy_mono_lib(libname_wo_ext):
|
||||
copy_file(
|
||||
mono_lib_path, "#bin", libname_wo_ext + ".a", "%s.iphone.%s.a" % (libname_wo_ext, arch)
|
||||
)
|
||||
|
||||
# Copy Mono libraries to the output folder. These are meant to be bundled with
|
||||
# the export templates and added to the Xcode project when exporting a game.
|
||||
copy_mono_lib("lib" + mono_lib)
|
||||
copy_mono_lib("libmono-native")
|
||||
copy_mono_lib("libmono-profiler-log")
|
||||
|
||||
if not is_ios_sim:
|
||||
copy_mono_lib("libmono-ee-interp")
|
||||
copy_mono_lib("libmono-icall-table")
|
||||
copy_mono_lib("libmono-ilgen")
|
||||
else:
|
||||
assert is_desktop(env["platform"]) or is_android or is_javascript
|
||||
env.Append(LINKFLAGS=["-Wl,-whole-archive", mono_lib_file, "-Wl,-no-whole-archive"])
|
||||
|
||||
if is_javascript:
|
||||
env.Append(LIBS=["mono-icall-table", "mono-native", "mono-ilgen", "mono-ee-interp"])
|
||||
|
||||
wasm_src_dir = os.path.join(mono_root, "src")
|
||||
if not os.path.isdir(wasm_src_dir):
|
||||
raise RuntimeError("Could not find mono wasm src directory")
|
||||
|
||||
# Ideally this should be defined only for 'driver.c', but I can't fight scons for another 2 hours
|
||||
env_mono.Append(CPPDEFINES=["CORE_BINDINGS"])
|
||||
|
||||
env_mono.add_source_files(
|
||||
env.modules_sources,
|
||||
[
|
||||
os.path.join(wasm_src_dir, "driver.c"),
|
||||
os.path.join(wasm_src_dir, "zlib-helper.c"),
|
||||
os.path.join(wasm_src_dir, "corebindings.c"),
|
||||
],
|
||||
)
|
||||
|
||||
env.Append(
|
||||
LINKFLAGS=[
|
||||
"--js-library",
|
||||
os.path.join(wasm_src_dir, "library_mono.js"),
|
||||
"--js-library",
|
||||
os.path.join(wasm_src_dir, "binding_support.js"),
|
||||
"--js-library",
|
||||
os.path.join(wasm_src_dir, "dotnet_support.js"),
|
||||
]
|
||||
)
|
||||
else:
|
||||
env.Append(LIBS=[mono_lib])
|
||||
|
||||
if is_macos:
|
||||
env.Append(LIBS=["iconv", "pthread"])
|
||||
elif is_android:
|
||||
pass # Nothing
|
||||
elif is_ios:
|
||||
pass # Nothing, linking is delegated to the exported Xcode project
|
||||
elif is_javascript:
|
||||
env.Append(LIBS=["m", "rt", "dl", "pthread"])
|
||||
else:
|
||||
env.Append(LIBS=["m", "rt", "dl", "pthread"])
|
||||
|
||||
if not mono_static:
|
||||
mono_so_file = find_file_in_dir(
|
||||
mono_lib_path, mono_lib_names, prefixes=["lib"], extensions=[sharedlib_ext]
|
||||
)
|
||||
|
||||
if not mono_so_file:
|
||||
raise RuntimeError("Could not find mono shared library in: " + mono_lib_path)
|
||||
else:
|
||||
assert not mono_static
|
||||
|
||||
# TODO: Add option to force using pkg-config
|
||||
print("Mono root directory not found. Using pkg-config instead")
|
||||
|
||||
env.ParseConfig("pkg-config monosgen-2 --libs")
|
||||
env_mono.ParseConfig("pkg-config monosgen-2 --cflags")
|
||||
|
||||
tmpenv = Environment()
|
||||
tmpenv.AppendENVPath("PKG_CONFIG_PATH", os.getenv("PKG_CONFIG_PATH"))
|
||||
tmpenv.ParseConfig("pkg-config monosgen-2 --libs-only-L")
|
||||
|
||||
for hint_dir in tmpenv["LIBPATH"]:
|
||||
file_found = find_file_in_dir(hint_dir, mono_lib_names, prefixes=["lib"], extensions=[sharedlib_ext])
|
||||
if file_found:
|
||||
mono_lib_path = hint_dir
|
||||
mono_so_file = file_found
|
||||
break
|
||||
|
||||
if not mono_so_file:
|
||||
raise RuntimeError("Could not find mono shared library in: " + str(tmpenv["LIBPATH"]))
|
||||
|
||||
if not mono_static:
|
||||
libs_output_dir = get_android_out_dir(env) if is_android else "#bin"
|
||||
copy_file(mono_lib_path, libs_output_dir, mono_so_file)
|
||||
|
||||
if not tools_enabled:
|
||||
if is_desktop(env["platform"]):
|
||||
if not mono_root:
|
||||
mono_root = (
|
||||
subprocess.check_output(["pkg-config", "mono-2", "--variable=prefix"]).decode("utf8").strip()
|
||||
)
|
||||
|
||||
make_template_dir(env, mono_root)
|
||||
elif is_android:
|
||||
# Compress Android Mono Config
|
||||
from . import make_android_mono_config
|
||||
|
||||
module_dir = os.getcwd()
|
||||
config_file_path = os.path.join(module_dir, "build_scripts", "mono_android_config.xml")
|
||||
make_android_mono_config.generate_compressed_config(config_file_path, "mono_gd/")
|
||||
|
||||
# Copy the required shared libraries
|
||||
copy_mono_shared_libs(env, mono_root, None)
|
||||
elif is_javascript:
|
||||
pass # No data directory for this platform
|
||||
elif is_ios:
|
||||
pass # No data directory for this platform
|
||||
|
||||
if copy_mono_root:
|
||||
if not mono_root:
|
||||
mono_root = subprocess.check_output(["pkg-config", "mono-2", "--variable=prefix"]).decode("utf8").strip()
|
||||
|
||||
if tools_enabled:
|
||||
# Only supported for editor builds.
|
||||
copy_mono_root_files(env, mono_root, mono_bcl)
|
||||
env.Append(LINKFLAGS=["-Wl,-whole-archive", libnethost_path, "-Wl,-no-whole-archive"])
|
||||
|
||||
|
||||
def make_template_dir(env, mono_root):
|
||||
from shutil import rmtree
|
||||
def determine_runtime_identifier(env):
|
||||
names_map = {
|
||||
"windows": "win",
|
||||
"osx": "osx",
|
||||
"linuxbsd": "linux",
|
||||
"server": "linux", # FIXME: Is server linux only, or also macos?
|
||||
}
|
||||
|
||||
platform = env["platform"]
|
||||
target = env["target"]
|
||||
|
||||
template_dir_name = ""
|
||||
|
||||
assert is_desktop(platform)
|
||||
|
||||
template_dir_name = "data.mono.%s.%s.%s" % (platform, env["bits"], target)
|
||||
|
||||
output_dir = Dir("#bin").abspath
|
||||
template_dir = os.path.join(output_dir, template_dir_name)
|
||||
|
||||
template_mono_root_dir = os.path.join(template_dir, "Mono")
|
||||
|
||||
if os.path.isdir(template_mono_root_dir):
|
||||
rmtree(template_mono_root_dir) # Clean first
|
||||
|
||||
# Copy etc/mono/
|
||||
|
||||
template_mono_config_dir = os.path.join(template_mono_root_dir, "etc", "mono")
|
||||
copy_mono_etc_dir(mono_root, template_mono_config_dir, platform)
|
||||
|
||||
# Copy the required shared libraries
|
||||
|
||||
copy_mono_shared_libs(env, mono_root, template_mono_root_dir)
|
||||
|
||||
|
||||
def copy_mono_root_files(env, mono_root, mono_bcl):
|
||||
from glob import glob
|
||||
from shutil import copy
|
||||
from shutil import rmtree
|
||||
|
||||
if not mono_root:
|
||||
raise RuntimeError("Mono installation directory not found")
|
||||
|
||||
output_dir = Dir("#bin").abspath
|
||||
editor_mono_root_dir = os.path.join(output_dir, "GodotSharp", "Mono")
|
||||
|
||||
if os.path.isdir(editor_mono_root_dir):
|
||||
rmtree(editor_mono_root_dir) # Clean first
|
||||
|
||||
# Copy etc/mono/
|
||||
|
||||
editor_mono_config_dir = os.path.join(editor_mono_root_dir, "etc", "mono")
|
||||
copy_mono_etc_dir(mono_root, editor_mono_config_dir, env["platform"])
|
||||
|
||||
# Copy the required shared libraries
|
||||
|
||||
copy_mono_shared_libs(env, mono_root, editor_mono_root_dir)
|
||||
|
||||
# Copy framework assemblies
|
||||
|
||||
mono_framework_dir = mono_bcl or os.path.join(mono_root, "lib", "mono", "4.5")
|
||||
mono_framework_facades_dir = os.path.join(mono_framework_dir, "Facades")
|
||||
|
||||
editor_mono_framework_dir = os.path.join(editor_mono_root_dir, "lib", "mono", "4.5")
|
||||
editor_mono_framework_facades_dir = os.path.join(editor_mono_framework_dir, "Facades")
|
||||
|
||||
if not os.path.isdir(editor_mono_framework_dir):
|
||||
os.makedirs(editor_mono_framework_dir)
|
||||
if not os.path.isdir(editor_mono_framework_facades_dir):
|
||||
os.makedirs(editor_mono_framework_facades_dir)
|
||||
|
||||
for assembly in glob(os.path.join(mono_framework_dir, "*.dll")):
|
||||
copy(assembly, editor_mono_framework_dir)
|
||||
for assembly in glob(os.path.join(mono_framework_facades_dir, "*.dll")):
|
||||
copy(assembly, editor_mono_framework_facades_dir)
|
||||
|
||||
|
||||
def copy_mono_etc_dir(mono_root, target_mono_config_dir, platform):
|
||||
from distutils.dir_util import copy_tree
|
||||
from glob import glob
|
||||
from shutil import copy
|
||||
|
||||
if not os.path.isdir(target_mono_config_dir):
|
||||
os.makedirs(target_mono_config_dir)
|
||||
|
||||
mono_etc_dir = os.path.join(mono_root, "etc", "mono")
|
||||
if not os.path.isdir(mono_etc_dir):
|
||||
mono_etc_dir = ""
|
||||
etc_hint_dirs = []
|
||||
if platform != "windows":
|
||||
etc_hint_dirs += ["/etc/mono", "/usr/local/etc/mono"]
|
||||
if "MONO_CFG_DIR" in os.environ:
|
||||
etc_hint_dirs += [os.path.join(os.environ["MONO_CFG_DIR"], "mono")]
|
||||
for etc_hint_dir in etc_hint_dirs:
|
||||
if os.path.isdir(etc_hint_dir):
|
||||
mono_etc_dir = etc_hint_dir
|
||||
break
|
||||
if not mono_etc_dir:
|
||||
raise RuntimeError("Mono installation etc directory not found")
|
||||
|
||||
copy_tree(os.path.join(mono_etc_dir, "2.0"), os.path.join(target_mono_config_dir, "2.0"))
|
||||
copy_tree(os.path.join(mono_etc_dir, "4.0"), os.path.join(target_mono_config_dir, "4.0"))
|
||||
copy_tree(os.path.join(mono_etc_dir, "4.5"), os.path.join(target_mono_config_dir, "4.5"))
|
||||
if os.path.isdir(os.path.join(mono_etc_dir, "mconfig")):
|
||||
copy_tree(os.path.join(mono_etc_dir, "mconfig"), os.path.join(target_mono_config_dir, "mconfig"))
|
||||
|
||||
for file in glob(os.path.join(mono_etc_dir, "*")):
|
||||
if os.path.isfile(file):
|
||||
copy(file, target_mono_config_dir)
|
||||
|
||||
|
||||
def copy_mono_shared_libs(env, mono_root, target_mono_root_dir):
|
||||
from shutil import copy
|
||||
|
||||
def copy_if_exists(src, dst):
|
||||
if os.path.isfile(src):
|
||||
copy(src, dst)
|
||||
# architectures names: x86, x64, arm, or arm64
|
||||
|
||||
platform = env["platform"]
|
||||
|
||||
if platform == "windows":
|
||||
src_mono_bin_dir = os.path.join(mono_root, "bin")
|
||||
target_mono_bin_dir = os.path.join(target_mono_root_dir, "bin")
|
||||
|
||||
if not os.path.isdir(target_mono_bin_dir):
|
||||
os.makedirs(target_mono_bin_dir)
|
||||
|
||||
mono_posix_helper_file = find_file_in_dir(
|
||||
src_mono_bin_dir, ["MonoPosixHelper"], prefixes=["", "lib"], extensions=[".dll"]
|
||||
)
|
||||
copy(
|
||||
os.path.join(src_mono_bin_dir, mono_posix_helper_file),
|
||||
os.path.join(target_mono_bin_dir, "MonoPosixHelper.dll"),
|
||||
)
|
||||
|
||||
# For newer versions
|
||||
btls_dll_path = os.path.join(src_mono_bin_dir, "libmono-btls-shared.dll")
|
||||
if os.path.isfile(btls_dll_path):
|
||||
copy(btls_dll_path, target_mono_bin_dir)
|
||||
if is_desktop(platform):
|
||||
bits = env["bits"]
|
||||
bit_arch_map = {"64": "x64", "32": "x86"}
|
||||
return "%s-%s" % (names_map[platform], bit_arch_map[bits])
|
||||
else:
|
||||
target_mono_lib_dir = (
|
||||
get_android_out_dir(env) if platform == "android" else os.path.join(target_mono_root_dir, "lib")
|
||||
)
|
||||
|
||||
if not os.path.isdir(target_mono_lib_dir):
|
||||
os.makedirs(target_mono_lib_dir)
|
||||
|
||||
lib_file_names = []
|
||||
if platform == "osx":
|
||||
lib_file_names = [
|
||||
lib_name + ".dylib"
|
||||
for lib_name in ["libmono-btls-shared", "libmono-native-compat", "libMonoPosixHelper"]
|
||||
]
|
||||
elif is_unix_like(platform):
|
||||
lib_file_names = [
|
||||
lib_name + ".so"
|
||||
for lib_name in [
|
||||
"libmono-btls-shared",
|
||||
"libmono-ee-interp",
|
||||
"libmono-native",
|
||||
"libMonoPosixHelper",
|
||||
"libmono-profiler-aot",
|
||||
"libmono-profiler-coverage",
|
||||
"libmono-profiler-log",
|
||||
"libMonoSupportW",
|
||||
]
|
||||
]
|
||||
|
||||
for lib_file_name in lib_file_names:
|
||||
copy_if_exists(os.path.join(mono_root, "lib", lib_file_name), target_mono_lib_dir)
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
def pkgconfig_try_find_mono_root(mono_lib_names, sharedlib_ext):
|
||||
tmpenv = Environment()
|
||||
tmpenv.AppendENVPath("PKG_CONFIG_PATH", os.getenv("PKG_CONFIG_PATH"))
|
||||
tmpenv.ParseConfig("pkg-config monosgen-2 --libs-only-L")
|
||||
for hint_dir in tmpenv["LIBPATH"]:
|
||||
name_found = find_name_in_dir_files(hint_dir, mono_lib_names, prefixes=["lib"], extensions=[sharedlib_ext])
|
||||
if name_found and os.path.isdir(os.path.join(hint_dir, "..", "include", "mono-2.0")):
|
||||
return os.path.join(hint_dir, "..")
|
||||
def find_app_host_version(dotnet_cmd, search_version):
|
||||
import subprocess
|
||||
|
||||
try:
|
||||
lines = subprocess.check_output([dotnet_cmd, "--list-runtimes"]).splitlines()
|
||||
|
||||
for line_bytes in lines:
|
||||
line = line_bytes.decode("utf-8")
|
||||
if not line.startswith("Microsoft.NETCore.App "):
|
||||
continue
|
||||
|
||||
parts = line.split(" ")
|
||||
if len(parts) < 2:
|
||||
continue
|
||||
|
||||
version = parts[1]
|
||||
|
||||
# Look for 6.0.0 or 6.0.0-*
|
||||
if version.startswith(search_version + "."):
|
||||
return version
|
||||
except (subprocess.CalledProcessError, OSError):
|
||||
pass
|
||||
return ""
|
||||
|
||||
|
||||
ENV_PATH_SEP = ";" if os.name == "nt" else ":"
|
||||
|
||||
|
||||
def find_executable(name):
|
||||
is_windows = os.name == "nt"
|
||||
windows_exts = os.environ["PATHEXT"].split(ENV_PATH_SEP) if is_windows else None
|
||||
path_dirs = os.environ["PATH"].split(ENV_PATH_SEP)
|
||||
|
||||
search_dirs = path_dirs + [os.getcwd()] # cwd is last in the list
|
||||
|
||||
for dir in search_dirs:
|
||||
path = os.path.join(dir, name)
|
||||
|
||||
if is_windows:
|
||||
for extension in windows_exts:
|
||||
path_with_ext = path + extension
|
||||
|
||||
if os.path.isfile(path_with_ext) and os.access(path_with_ext, os.X_OK):
|
||||
return path_with_ext
|
||||
else:
|
||||
if os.path.isfile(path) and os.access(path, os.X_OK):
|
||||
return path
|
||||
|
||||
return ""
|
||||
|
|
|
@ -1,113 +0,0 @@
|
|||
import os
|
||||
import platform
|
||||
|
||||
if os.name == "nt":
|
||||
import sys
|
||||
import winreg
|
||||
|
||||
|
||||
def _reg_open_key(key, subkey):
|
||||
try:
|
||||
return winreg.OpenKey(key, subkey)
|
||||
except OSError:
|
||||
if platform.architecture()[0] == "32bit":
|
||||
bitness_sam = winreg.KEY_WOW64_64KEY
|
||||
else:
|
||||
bitness_sam = winreg.KEY_WOW64_32KEY
|
||||
return winreg.OpenKey(key, subkey, 0, winreg.KEY_READ | bitness_sam)
|
||||
|
||||
|
||||
def _reg_open_key_bits(key, subkey, bits):
|
||||
sam = winreg.KEY_READ
|
||||
|
||||
if platform.architecture()[0] == "32bit":
|
||||
if bits == "64":
|
||||
# Force 32bit process to search in 64bit registry
|
||||
sam |= winreg.KEY_WOW64_64KEY
|
||||
else:
|
||||
if bits == "32":
|
||||
# Force 64bit process to search in 32bit registry
|
||||
sam |= winreg.KEY_WOW64_32KEY
|
||||
|
||||
return winreg.OpenKey(key, subkey, 0, sam)
|
||||
|
||||
|
||||
def _find_mono_in_reg(subkey, bits):
|
||||
try:
|
||||
with _reg_open_key_bits(winreg.HKEY_LOCAL_MACHINE, subkey, bits) as hKey:
|
||||
value = winreg.QueryValueEx(hKey, "SdkInstallRoot")[0]
|
||||
return value
|
||||
except OSError:
|
||||
return None
|
||||
|
||||
|
||||
def _find_mono_in_reg_old(subkey, bits):
|
||||
try:
|
||||
with _reg_open_key_bits(winreg.HKEY_LOCAL_MACHINE, subkey, bits) as hKey:
|
||||
default_clr = winreg.QueryValueEx(hKey, "DefaultCLR")[0]
|
||||
if default_clr:
|
||||
return _find_mono_in_reg(subkey + "\\" + default_clr, bits)
|
||||
return None
|
||||
except OSError:
|
||||
return None
|
||||
|
||||
|
||||
def find_mono_root_dir(bits):
|
||||
root_dir = _find_mono_in_reg(r"SOFTWARE\Mono", bits)
|
||||
if root_dir is not None:
|
||||
return str(root_dir)
|
||||
root_dir = _find_mono_in_reg_old(r"SOFTWARE\Novell\Mono", bits)
|
||||
if root_dir is not None:
|
||||
return str(root_dir)
|
||||
return ""
|
||||
|
||||
|
||||
def find_msbuild_tools_path_reg():
|
||||
import subprocess
|
||||
|
||||
vswhere = os.getenv("PROGRAMFILES(X86)")
|
||||
if not vswhere:
|
||||
vswhere = os.getenv("PROGRAMFILES")
|
||||
vswhere += r"\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: " + e.message)
|
||||
except OSError:
|
||||
pass # Fine, vswhere not found
|
||||
except (subprocess.CalledProcessError, OSError):
|
||||
pass
|
||||
|
||||
# Try to find 14.0 in the Registry
|
||||
|
||||
try:
|
||||
subkey = r"SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0"
|
||||
with _reg_open_key(winreg.HKEY_LOCAL_MACHINE, subkey) as hKey:
|
||||
value = winreg.QueryValueEx(hKey, "MSBuildToolsPath")[0]
|
||||
return value
|
||||
except OSError:
|
||||
return ""
|
|
@ -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")
|
|
@ -1,8 +1,10 @@
|
|||
supported_platforms = ["windows", "osx", "linuxbsd", "server", "android", "haiku", "javascript", "iphone"]
|
||||
# Prior to .NET Core, we supported these: ["windows", "osx", "linuxbsd", "server", "android", "haiku", "javascript", "iphone"]
|
||||
# Eventually support for each them should be added back (except Haiku if not supported by .NET Core)
|
||||
supported_platforms = ["windows", "osx", "linuxbsd", "server"]
|
||||
|
||||
|
||||
def can_build(env, platform):
|
||||
return True
|
||||
return env["module_gdnative_enabled"]
|
||||
|
||||
|
||||
def configure(env):
|
||||
|
@ -13,52 +15,21 @@ def configure(env):
|
|||
|
||||
env.add_module_version_string("mono")
|
||||
|
||||
from SCons.Script import BoolVariable, PathVariable, Variables, Help
|
||||
|
||||
default_mono_static = platform in ["iphone", "javascript"]
|
||||
default_mono_bundles_zlib = platform in ["javascript"]
|
||||
from SCons.Script import PathVariable, Variables, Help
|
||||
|
||||
envvars = Variables()
|
||||
envvars.Add(
|
||||
PathVariable(
|
||||
"mono_prefix",
|
||||
"Path to the Mono installation directory for the target platform and architecture",
|
||||
"dotnet_root",
|
||||
"Path to the .NET Sdk installation directory for the target platform and architecture",
|
||||
"",
|
||||
PathVariable.PathAccept,
|
||||
)
|
||||
)
|
||||
envvars.Add(
|
||||
PathVariable(
|
||||
"mono_bcl",
|
||||
"Path to a custom Mono BCL (Base Class Library) directory for the target platform",
|
||||
"",
|
||||
PathVariable.PathAccept,
|
||||
)
|
||||
)
|
||||
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)
|
||||
)
|
||||
|
||||
# TODO: It would be great if this could be detected automatically instead
|
||||
envvars.Add(
|
||||
BoolVariable(
|
||||
"mono_bundles_zlib", "Specify if the Mono runtime was built with bundled zlib", default_mono_bundles_zlib
|
||||
)
|
||||
)
|
||||
|
||||
envvars.Update(env)
|
||||
Help(envvars.GenerateHelpText(env))
|
||||
|
||||
if env["mono_bundles_zlib"]:
|
||||
# Mono may come with zlib bundled for WASM or on newer version when built with MinGW.
|
||||
print("This Mono runtime comes with zlib bundled. Disabling 'builtin_zlib'...")
|
||||
env["builtin_zlib"] = False
|
||||
thirdparty_zlib_dir = "#thirdparty/zlib/"
|
||||
env.Prepend(CPPPATH=[thirdparty_zlib_dir])
|
||||
|
||||
|
||||
def get_doc_classes():
|
||||
return [
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -39,8 +39,6 @@
|
|||
|
||||
#include "mono_gc_handle.h"
|
||||
#include "mono_gd/gd_mono.h"
|
||||
#include "mono_gd/gd_mono_header.h"
|
||||
#include "mono_gd/gd_mono_internals.h"
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
#include "editor/editor_plugin.h"
|
||||
|
@ -66,18 +64,6 @@ TScriptInstance *cast_script_instance(ScriptInstance *p_inst) {
|
|||
|
||||
#define CAST_CSHARP_INSTANCE(m_inst) (cast_script_instance<CSharpInstance, CSharpLanguage>(m_inst))
|
||||
|
||||
struct DotNetScriptLookupInfo {
|
||||
String class_namespace;
|
||||
String class_name;
|
||||
GDMonoClass *script_class = nullptr;
|
||||
|
||||
DotNetScriptLookupInfo() {} // Required by HashMap...
|
||||
|
||||
DotNetScriptLookupInfo(const String &p_class_namespace, const String &p_class_name, GDMonoClass *p_script_class) :
|
||||
class_namespace(p_class_namespace), class_name(p_class_name), script_class(p_script_class) {
|
||||
}
|
||||
};
|
||||
|
||||
class CSharpScript : public Script {
|
||||
GDCLASS(CSharpScript, Script);
|
||||
|
||||
|
@ -88,26 +74,13 @@ public:
|
|||
bool nil_is_variant = false;
|
||||
};
|
||||
|
||||
struct EventSignal {
|
||||
GDMonoField *field = nullptr;
|
||||
GDMonoMethod *invoke_method = nullptr;
|
||||
Vector<SignalParameter> parameters;
|
||||
};
|
||||
|
||||
private:
|
||||
friend class CSharpInstance;
|
||||
friend class CSharpLanguage;
|
||||
friend struct CSharpScriptDepSort;
|
||||
|
||||
bool tool = false;
|
||||
bool valid = false;
|
||||
|
||||
bool builtin;
|
||||
|
||||
GDMonoClass *base = nullptr;
|
||||
GDMonoClass *native = nullptr;
|
||||
GDMonoClass *script_class = nullptr;
|
||||
|
||||
Ref<CSharpScript> base_cache; // TODO what's this for?
|
||||
|
||||
Set<Object *> instances;
|
||||
|
@ -128,14 +101,9 @@ private:
|
|||
#endif
|
||||
|
||||
String source;
|
||||
StringName name;
|
||||
|
||||
SelfList<CSharpScript> script_list = this;
|
||||
|
||||
Map<StringName, Vector<SignalParameter>> _signals;
|
||||
Map<StringName, EventSignal> event_signals;
|
||||
bool signals_invalidated = true;
|
||||
|
||||
Vector<MultiplayerAPI::RPCConfig> rpc_functions;
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
|
@ -158,34 +126,26 @@ private:
|
|||
|
||||
void _clear();
|
||||
|
||||
void _update_name();
|
||||
|
||||
void load_script_signals(GDMonoClass *p_class, GDMonoClass *p_native_class);
|
||||
bool _get_signal(GDMonoClass *p_class, GDMonoMethod *p_delegate_invoke, Vector<SignalParameter> ¶ms);
|
||||
|
||||
bool _update_exports(PlaceHolderScriptInstance *p_instance_to_update = nullptr);
|
||||
|
||||
#warning TODO
|
||||
#if 0
|
||||
bool _get_member_export(IMonoClassMember *p_member, bool p_inspect_export, PropertyInfo &r_prop_info, bool &r_exported);
|
||||
#ifdef TOOLS_ENABLED
|
||||
static int _try_get_member_export_hint(IMonoClassMember *p_member, ManagedType p_type, Variant::Type p_variant_type, bool p_allow_generics, PropertyHint &r_hint, String &r_hint_string);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
CSharpInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_is_ref_counted, Callable::CallError &r_error);
|
||||
Variant _new(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
|
||||
|
||||
// Do not use unless you know what you are doing
|
||||
friend void GDMonoInternals::tie_managed_to_unmanaged(MonoObject *, Object *);
|
||||
static Ref<CSharpScript> create_for_managed_type(GDMonoClass *p_class, GDMonoClass *p_native);
|
||||
static void update_script_class_info(Ref<CSharpScript> p_script);
|
||||
static void initialize_for_managed_type(Ref<CSharpScript> p_script, GDMonoClass *p_class, GDMonoClass *p_native);
|
||||
|
||||
MultiplayerAPI::RPCMode _member_get_rpc_mode(IMonoClassMember *p_member) const;
|
||||
static void initialize_for_managed_type(Ref<CSharpScript> p_script);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override;
|
||||
void _resource_path_changed() override;
|
||||
bool _get(const StringName &p_name, Variant &r_ret) const;
|
||||
bool _set(const StringName &p_name, const Variant &p_value);
|
||||
void _get_property_list(List<PropertyInfo> *p_properties) const;
|
||||
|
@ -270,22 +230,21 @@ class CSharpInstance : public ScriptInstance {
|
|||
bool _unreference_owner_unsafe();
|
||||
|
||||
/*
|
||||
* If nullptr is returned, the caller must destroy the script instance by removing it from its owner.
|
||||
* If false is returned, the caller must destroy the script instance by removing it from its owner.
|
||||
*/
|
||||
MonoObject *_internal_new_managed();
|
||||
bool _internal_new_managed();
|
||||
|
||||
// Do not use unless you know what you are doing
|
||||
friend void GDMonoInternals::tie_managed_to_unmanaged(MonoObject *, Object *);
|
||||
static CSharpInstance *create_for_managed_type(Object *p_owner, CSharpScript *p_script, const MonoGCHandleData &p_gchandle);
|
||||
|
||||
void get_properties_state_for_reloading(List<Pair<StringName, Variant>> &r_state);
|
||||
void get_event_signals_state_for_reloading(List<Pair<StringName, Array>> &r_state);
|
||||
|
||||
public:
|
||||
MonoObject *get_mono_object() const;
|
||||
|
||||
_FORCE_INLINE_ bool is_destructing_script_instance() { return destructing_script_instance; }
|
||||
|
||||
_FORCE_INLINE_ GCHandleIntPtr get_gchandle_intptr() { return gchandle.get_intptr(); }
|
||||
|
||||
Object *get_owner() override;
|
||||
|
||||
bool set(const StringName &p_name, const Variant &p_value) override;
|
||||
|
@ -297,15 +256,15 @@ public:
|
|||
bool has_method(const StringName &p_method) const override;
|
||||
Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Callable::CallError &r_error) override;
|
||||
|
||||
void mono_object_disposed(MonoObject *p_obj);
|
||||
void mono_object_disposed();
|
||||
|
||||
/*
|
||||
* If 'r_delete_owner' is set to true, the caller must memdelete the script instance's owner. Otherwise, if
|
||||
* 'r_remove_script_instance' is set to true, the caller must destroy the script instance by removing it from its owner.
|
||||
*/
|
||||
void mono_object_disposed_baseref(MonoObject *p_obj, bool p_is_finalizer, bool &r_delete_owner, bool &r_remove_script_instance);
|
||||
void mono_object_disposed_baseref(bool p_is_finalizer, bool &r_delete_owner, bool &r_remove_script_instance);
|
||||
|
||||
void connect_event_signals();
|
||||
void connect_event_signal(const StringName &p_event_signal);
|
||||
void disconnect_event_signals();
|
||||
|
||||
void refcount_incremented() override;
|
||||
|
@ -329,7 +288,6 @@ public:
|
|||
struct CSharpScriptBinding {
|
||||
bool inited = false;
|
||||
StringName type_name;
|
||||
GDMonoClass *wrapper_class = nullptr;
|
||||
MonoGCHandleData gchandle;
|
||||
Object *owner = nullptr;
|
||||
|
||||
|
@ -367,33 +325,22 @@ class CSharpLanguage : public ScriptLanguage {
|
|||
ManagedCallableMiddleman *managed_callable_middleman = memnew(ManagedCallableMiddleman);
|
||||
|
||||
struct StringNameCache {
|
||||
StringName _signal_callback;
|
||||
StringName _set;
|
||||
StringName _get;
|
||||
StringName _get_property_list;
|
||||
StringName _notification;
|
||||
StringName _script_source;
|
||||
StringName dotctor; // .ctor
|
||||
StringName on_before_serialize; // OnBeforeSerialize
|
||||
StringName on_after_deserialize; // OnAfterDeserialize
|
||||
StringName delegate_invoke_method_name;
|
||||
|
||||
StringNameCache();
|
||||
};
|
||||
|
||||
int lang_idx = -1;
|
||||
|
||||
HashMap<String, DotNetScriptLookupInfo> dotnet_script_lookup_map;
|
||||
|
||||
void lookup_script_for_class(GDMonoClass *p_class);
|
||||
|
||||
// For debug_break and debug_break_parse
|
||||
int _debug_parse_err_line = -1;
|
||||
String _debug_parse_err_file;
|
||||
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;
|
||||
|
@ -416,6 +363,7 @@ public:
|
|||
StringNameCache string_names;
|
||||
|
||||
const Mutex &get_language_bind_mutex() { return language_bind_mutex; }
|
||||
const Mutex &get_script_instances_mutex() { return script_instances_mutex; }
|
||||
|
||||
_FORCE_INLINE_ int get_language_index() { return lang_idx; }
|
||||
void set_language_index(int p_idx);
|
||||
|
@ -429,7 +377,7 @@ public:
|
|||
#endif
|
||||
|
||||
static void release_script_gchandle(MonoGCHandleData &p_gchandle);
|
||||
static void release_script_gchandle(MonoObject *p_expected_obj, MonoGCHandleData &p_gchandle);
|
||||
static void release_script_gchandle(void *p_expected_mono_obj_unused, MonoGCHandleData &p_gchandle);
|
||||
|
||||
bool debug_break(const String &p_error, bool p_allow_continue = true);
|
||||
bool debug_break_parse(const String &p_file, int p_line, const String &p_error);
|
||||
|
@ -441,12 +389,6 @@ public:
|
|||
|
||||
_FORCE_INLINE_ ManagedCallableMiddleman *get_managed_callable_middleman() const { return managed_callable_middleman; }
|
||||
|
||||
void lookup_scripts_in_assembly(GDMonoAssembly *p_assembly);
|
||||
|
||||
const DotNetScriptLookupInfo *lookup_dotnet_script(const String &p_script_path) const {
|
||||
return dotnet_script_lookup_map.getptr(p_script_path);
|
||||
}
|
||||
|
||||
String get_name() const override;
|
||||
|
||||
/* LANGUAGE FUNCTIONS */
|
||||
|
@ -514,15 +456,18 @@ public:
|
|||
bool overrides_external_editor() override;
|
||||
#endif
|
||||
|
||||
/* THREAD ATTACHING */
|
||||
void thread_enter() override;
|
||||
void thread_exit() override;
|
||||
|
||||
Map<Object *, CSharpScriptBinding>::Element *insert_script_binding(Object *p_object, const CSharpScriptBinding &p_script_binding);
|
||||
bool setup_csharp_script_binding(CSharpScriptBinding &r_script_binding, Object *p_object);
|
||||
|
||||
static void tie_native_managed_to_unmanaged(GCHandleIntPtr p_gchandle_intptr, Object *p_unmanaged, const StringName *p_native_name, bool p_ref_counted);
|
||||
static void tie_user_managed_to_unmanaged(GCHandleIntPtr p_gchandle_intptr, Object *p_unmanaged, CSharpScript *p_script, bool p_ref_counted);
|
||||
static void tie_managed_to_unmanaged_with_pre_setup(GCHandleIntPtr p_gchandle_intptr, Object *p_unmanaged);
|
||||
|
||||
#warning TODO
|
||||
#if 0
|
||||
#ifdef DEBUG_ENABLED
|
||||
Vector<StackInfo> stack_trace_get_info(MonoObject *p_stack_trace);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void post_unsafe_reference(Object *p_obj);
|
||||
|
|
|
@ -12,8 +12,7 @@
|
|||
</tutorials>
|
||||
<methods>
|
||||
<method name="new" qualifiers="vararg">
|
||||
<return type="Variant">
|
||||
</return>
|
||||
<return type="Variant" />
|
||||
<description>
|
||||
Returns a new instance of the script.
|
||||
</description>
|
||||
|
|
|
@ -10,64 +10,10 @@
|
|||
<tutorials>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="attach_thread">
|
||||
<return type="void">
|
||||
</return>
|
||||
<description>
|
||||
Attaches the current thread to the Mono runtime.
|
||||
</description>
|
||||
</method>
|
||||
<method name="detach_thread">
|
||||
<return type="void">
|
||||
</return>
|
||||
<description>
|
||||
Detaches the current thread from the Mono runtime.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_domain_id">
|
||||
<return type="int">
|
||||
</return>
|
||||
<description>
|
||||
Returns the current MonoDomain ID.
|
||||
[b]Note:[/b] The Mono runtime must be initialized for this method to work (use [method is_runtime_initialized] to check). If the Mono runtime isn't initialized at the time this method is called, the engine will crash.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_scripts_domain_id">
|
||||
<return type="int">
|
||||
</return>
|
||||
<description>
|
||||
Returns the scripts MonoDomain's ID. This will be the same MonoDomain ID as [method get_domain_id], unless the scripts domain isn't loaded.
|
||||
[b]Note:[/b] The Mono runtime must be initialized for this method to work (use [method is_runtime_initialized] to check). If the Mono runtime isn't initialized at the time this method is called, the engine will crash.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_domain_finalizing_for_unload">
|
||||
<return type="bool">
|
||||
</return>
|
||||
<argument index="0" name="domain_id" type="int">
|
||||
</argument>
|
||||
<description>
|
||||
Returns [code]true[/code] if the domain is being finalized, [code]false[/code] otherwise.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_runtime_initialized">
|
||||
<return type="bool">
|
||||
</return>
|
||||
<return type="bool" />
|
||||
<description>
|
||||
Returns [code]true[/code] if the Mono runtime is initialized, [code]false[/code] otherwise.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_runtime_shutting_down">
|
||||
<return type="bool">
|
||||
</return>
|
||||
<description>
|
||||
Returns [code]true[/code] if the Mono runtime is shutting down, [code]false[/code] otherwise.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_scripts_domain_loaded">
|
||||
<return type="bool">
|
||||
</return>
|
||||
<description>
|
||||
Returns [code]true[/code] if the scripts domain is loaded, [code]false[/code] otherwise.
|
||||
Returns [code]true[/code] if the .NET runtime is initialized, [code]false[/code] otherwise.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Godot.NET.Sdk", "Godot.NET.Sdk\Godot.NET.Sdk.csproj", "{31B00BFA-DEA1-42FA-A472-9E54A92A8A5F}"
|
||||
EndProject
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
|
|
@ -5,6 +5,6 @@
|
|||
<LangVersion>7.2</LangVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Build.Framework" Version="16.5.0" />
|
||||
<PackageReference Include="Microsoft.Build.Framework" Version="15.1.548" ExcludeAssets="runtime" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{639E48BD-44E5-4091-8EDD-22D36DC0768D}</ProjectGuid>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<LangVersion>7.2</LangVersion>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{B06C2951-C8E3-4F28-80B2-717CF327EB19}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{EAFFF236-FA96-4A4D-BD23-0E51EF988277}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
|
|
|
@ -1,32 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}</ProjectGuid>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<LangVersion>7.2</LangVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Build" Version="16.5.0" />
|
||||
<PackageReference Include="Microsoft.Build" Version="15.1.548" ExcludeAssets="runtime" />
|
||||
<PackageReference Include="Microsoft.Build.Locator" Version="1.2.6" />
|
||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\GodotTools.Core\GodotTools.Core.csproj" />
|
||||
<ProjectReference Include="..\GodotTools.Shared\GodotTools.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
<!--
|
||||
The Microsoft.Build.Runtime package is too problematic so we create a MSBuild.exe stub. The workaround described
|
||||
here doesn't work with Microsoft.NETFramework.ReferenceAssemblies: https://github.com/microsoft/msbuild/issues/3486
|
||||
We need a MSBuild.exe file as there's an issue in Microsoft.Build where it executes platform dependent code when
|
||||
searching for MSBuild.exe before the fallback to not using it. A stub is fine as it should never be executed.
|
||||
-->
|
||||
<ItemGroup>
|
||||
<None Include="MSBuild.exe" CopyToOutputDirectory="Always" />
|
||||
</ItemGroup>
|
||||
<Target Name="CopyMSBuildStubWindows" AfterTargets="Build" Condition=" '$(GodotPlatform)' == 'windows' Or ( '$(GodotPlatform)' == '' And '$(OS)' == 'Windows_NT' ) ">
|
||||
<PropertyGroup>
|
||||
<GodotSourceRootPath>$(SolutionDir)/../../../../</GodotSourceRootPath>
|
||||
<GodotOutputDataDir>$(GodotSourceRootPath)/bin/GodotSharp</GodotOutputDataDir>
|
||||
</PropertyGroup>
|
||||
<!-- Need to copy it here as well on Windows -->
|
||||
<Copy SourceFiles="MSBuild.exe" DestinationFiles="$(GodotOutputDataDir)\Mono\lib\mono\v4.0\MSBuild.exe" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
|
|
@ -21,7 +21,8 @@ namespace GodotTools.ProjectEditor
|
|||
root.Sdk = GodotSdkAttrValue;
|
||||
|
||||
var mainGroup = root.AddPropertyGroup();
|
||||
mainGroup.AddProperty("TargetFramework", "netstandard2.1");
|
||||
mainGroup.AddProperty("TargetFramework", "net5.0");
|
||||
mainGroup.AddProperty("EnableDynamicLoading", "true");
|
||||
|
||||
string sanitizedName = IdentifierUtils.SanitizeQualifiedIdentifier(name, allowEmptyIdentifiers: true);
|
||||
|
||||
|
|
|
@ -19,6 +19,9 @@ namespace GodotTools.ProjectEditor
|
|||
|
||||
public static class ProjectUtils
|
||||
{
|
||||
public static void MSBuildLocatorRegisterDefaults()
|
||||
=> Microsoft.Build.Locator.MSBuildLocator.RegisterDefaults();
|
||||
|
||||
public static MSBuildProject Open(string path)
|
||||
{
|
||||
var root = ProjectRootElement.Open(path);
|
||||
|
@ -42,7 +45,8 @@ namespace GodotTools.ProjectEditor
|
|||
var root = project.Root;
|
||||
string godotSdkAttrValue = ProjectGenerator.GodotSdkAttrValue;
|
||||
|
||||
if (!string.IsNullOrEmpty(root.Sdk) && root.Sdk.Trim().Equals(godotSdkAttrValue, StringComparison.OrdinalIgnoreCase))
|
||||
if (!string.IsNullOrEmpty(root.Sdk) &&
|
||||
root.Sdk.Trim().Equals(godotSdkAttrValue, StringComparison.OrdinalIgnoreCase))
|
||||
return;
|
||||
|
||||
root.Sdk = godotSdkAttrValue;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
<Import Project="GenerateGodotNupkgsVersions.targets" />
|
||||
</Project>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2012
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotTools.ProjectEditor", "GodotTools.ProjectEditor\GodotTools.ProjectEditor.csproj", "{A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}"
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using GodotTools.Ides.Rider;
|
||||
using GodotTools.Internals;
|
||||
using JetBrains.Annotations;
|
||||
using static GodotTools.Internals.Globals;
|
||||
using File = GodotTools.Utils.File;
|
||||
using OS = GodotTools.Utils.OS;
|
||||
|
@ -159,7 +159,7 @@ namespace GodotTools.Build
|
|||
}
|
||||
}
|
||||
|
||||
public static bool BuildProjectBlocking(string config, [CanBeNull] string[] targets = null, [CanBeNull] string platform = null)
|
||||
public static bool BuildProjectBlocking(string config, [MaybeNull] string[] targets = null, [MaybeNull] string platform = null)
|
||||
{
|
||||
var buildInfo = new BuildInfo(GodotSharpDirs.ProjectSlnPath, targets ?? new[] {"Build"}, config, restore: true);
|
||||
|
||||
|
@ -178,17 +178,6 @@ namespace GodotTools.Build
|
|||
if (!File.Exists(buildInfo.Solution))
|
||||
return true; // No solution to build
|
||||
|
||||
// Make sure the API assemblies are up to date before building the project.
|
||||
// We may not have had the chance to update the release API assemblies, and the debug ones
|
||||
// may have been deleted by the user at some point after they were loaded by the Godot editor.
|
||||
string apiAssembliesUpdateError = Internal.UpdateApiAssembliesFromPrebuilt(buildInfo.Configuration == "ExportRelease" ? "Release" : "Debug");
|
||||
|
||||
if (!string.IsNullOrEmpty(apiAssembliesUpdateError))
|
||||
{
|
||||
ShowBuildErrorDialog("Failed to update the Godot API assemblies");
|
||||
return false;
|
||||
}
|
||||
|
||||
using (var pr = new EditorProgress("mono_project_debug_build", "Building project solution...", 1))
|
||||
{
|
||||
pr.Step("Building project solution", 0);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
using Godot;
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Godot.Collections;
|
||||
using GodotTools.Internals;
|
||||
using JetBrains.Annotations;
|
||||
using File = GodotTools.Utils.File;
|
||||
using Path = System.IO.Path;
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System;
|
||||
using Godot;
|
||||
using GodotTools.Internals;
|
||||
using JetBrains.Annotations;
|
||||
using static GodotTools.Internals.Globals;
|
||||
using File = GodotTools.Utils.File;
|
||||
|
||||
|
@ -28,7 +27,6 @@ namespace GodotTools.Build
|
|||
BuildOutputView.UpdateIssuesList();
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
public void BuildSolution()
|
||||
{
|
||||
if (!File.Exists(GodotSharpDirs.ProjectSlnPath))
|
||||
|
@ -57,7 +55,6 @@ namespace GodotTools.Build
|
|||
Internal.ReloadAssemblies(softReload: false);
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
private void RebuildSolution()
|
||||
{
|
||||
if (!File.Exists(GodotSharpDirs.ProjectSlnPath))
|
||||
|
@ -86,7 +83,6 @@ namespace GodotTools.Build
|
|||
Internal.ReloadAssemblies(softReload: false);
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
private void CleanSolution()
|
||||
{
|
||||
if (!File.Exists(GodotSharpDirs.ProjectSlnPath))
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
using Godot;
|
||||
using Godot.NativeInterop;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using GodotTools.Build;
|
||||
using GodotTools.Core;
|
||||
using GodotTools.Internals;
|
||||
using JetBrains.Annotations;
|
||||
using static GodotTools.Internals.Globals;
|
||||
using Directory = GodotTools.Utils.Directory;
|
||||
using File = GodotTools.Utils.File;
|
||||
|
@ -100,7 +101,9 @@ namespace GodotTools.Export
|
|||
return;
|
||||
|
||||
if (Path.GetExtension(path) != Internal.CSharpLanguageExtension)
|
||||
throw new ArgumentException($"Resource of type {Internal.CSharpLanguageType} has an invalid file extension: {path}", nameof(path));
|
||||
throw new ArgumentException(
|
||||
$"Resource of type {Internal.CSharpLanguageType} has an invalid file extension: {path}",
|
||||
nameof(path));
|
||||
|
||||
// TODO What if the source file is not part of the game's C# project
|
||||
|
||||
|
@ -194,7 +197,8 @@ namespace GodotTools.Export
|
|||
{
|
||||
string thisWasmFrameworkAssemblyPath = Path.Combine(bclDir, thisWasmFrameworkAssemblyName + ".dll");
|
||||
if (!File.Exists(thisWasmFrameworkAssemblyPath))
|
||||
throw new FileNotFoundException($"Assembly not found: '{thisWasmFrameworkAssemblyName}'", thisWasmFrameworkAssemblyPath);
|
||||
throw new FileNotFoundException($"Assembly not found: '{thisWasmFrameworkAssemblyName}'",
|
||||
thisWasmFrameworkAssemblyPath);
|
||||
assemblies[thisWasmFrameworkAssemblyName] = thisWasmFrameworkAssemblyPath;
|
||||
}
|
||||
|
||||
|
@ -206,17 +210,20 @@ namespace GodotTools.Export
|
|||
|
||||
foreach (var thisWasmFrameworkAssemblyName in wasmFrameworkAssembliesOneOf)
|
||||
{
|
||||
string thisWasmFrameworkAssemblyPath = Path.Combine(bclDir, thisWasmFrameworkAssemblyName.newName + ".dll");
|
||||
string thisWasmFrameworkAssemblyPath =
|
||||
Path.Combine(bclDir, thisWasmFrameworkAssemblyName.newName + ".dll");
|
||||
if (File.Exists(thisWasmFrameworkAssemblyPath))
|
||||
{
|
||||
assemblies[thisWasmFrameworkAssemblyName.newName] = thisWasmFrameworkAssemblyPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
thisWasmFrameworkAssemblyPath = Path.Combine(bclDir, thisWasmFrameworkAssemblyName.oldName + ".dll");
|
||||
thisWasmFrameworkAssemblyPath =
|
||||
Path.Combine(bclDir, thisWasmFrameworkAssemblyName.oldName + ".dll");
|
||||
if (!File.Exists(thisWasmFrameworkAssemblyPath))
|
||||
{
|
||||
throw new FileNotFoundException("Expected one of the following assemblies but none were found: " +
|
||||
throw new FileNotFoundException(
|
||||
"Expected one of the following assemblies but none were found: " +
|
||||
$"'{thisWasmFrameworkAssemblyName.newName}' / '{thisWasmFrameworkAssemblyName.oldName}'",
|
||||
thisWasmFrameworkAssemblyPath);
|
||||
}
|
||||
|
@ -227,7 +234,13 @@ namespace GodotTools.Export
|
|||
}
|
||||
|
||||
var initialAssemblies = assemblies.Duplicate();
|
||||
internal_GetExportedAssemblyDependencies(initialAssemblies, buildConfig, bclDir, assemblies);
|
||||
godot_dictionary initialAssembliesAux = ((Godot.Collections.Dictionary)initialAssemblies).NativeValue;
|
||||
using godot_string buildConfigAux = Marshaling.mono_string_to_godot(buildConfig);
|
||||
using godot_string bclDirAux = Marshaling.mono_string_to_godot(bclDir);
|
||||
godot_dictionary assembliesAux = ((Godot.Collections.Dictionary)assemblies).NativeValue;
|
||||
// TODO
|
||||
throw new NotImplementedException();
|
||||
//internal_GetExportedAssemblyDependencies(initialAssembliesAux, buildConfigAux, bclDirAux, ref assembliesAux);
|
||||
|
||||
AddI18NAssemblies(assemblies, bclDir);
|
||||
|
||||
|
@ -237,9 +250,12 @@ namespace GodotTools.Export
|
|||
outputDataDir = ExportDataDirectory(features, platform, isDebug, outputDir);
|
||||
|
||||
string apiConfig = isDebug ? "Debug" : "Release";
|
||||
string resAssembliesDir = Path.Combine(GodotSharpDirs.ResAssembliesBaseDir, apiConfig);
|
||||
// TODO
|
||||
throw new NotImplementedException();
|
||||
string resAssembliesDir = null; // Path.Combine(GodotSharpDirs.ResAssembliesBaseDir, apiConfig);
|
||||
|
||||
bool assembliesInsidePck = (bool)ProjectSettings.GetSetting("mono/export/export_assemblies_inside_pck") || outputDataDir == null;
|
||||
bool assembliesInsidePck = (bool)ProjectSettings.GetSetting("mono/export/export_assemblies_inside_pck") ||
|
||||
outputDataDir == null;
|
||||
|
||||
if (!assembliesInsidePck)
|
||||
{
|
||||
|
@ -277,7 +293,8 @@ namespace GodotTools.Export
|
|||
}
|
||||
|
||||
// AOT compilation
|
||||
bool aotEnabled = platform == OS.Platforms.iOS || (bool)ProjectSettings.GetSetting("mono/export/aot/enabled");
|
||||
bool aotEnabled = platform == OS.Platforms.iOS ||
|
||||
(bool)ProjectSettings.GetSetting("mono/export/aot/enabled");
|
||||
|
||||
if (aotEnabled)
|
||||
{
|
||||
|
@ -296,14 +313,19 @@ namespace GodotTools.Export
|
|||
LLVMOnly = false,
|
||||
LLVMPath = "",
|
||||
LLVMOutputPath = "",
|
||||
FullAot = platform == OS.Platforms.iOS || (bool)(ProjectSettings.GetSetting("mono/export/aot/full_aot") ?? false),
|
||||
FullAot = platform == OS.Platforms.iOS ||
|
||||
(bool)(ProjectSettings.GetSetting("mono/export/aot/full_aot") ?? false),
|
||||
UseInterpreter = (bool)ProjectSettings.GetSetting("mono/export/aot/use_interpreter"),
|
||||
ExtraAotOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_aot_options") ?? Array.Empty<string>(),
|
||||
ExtraOptimizerOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_optimizer_options") ?? Array.Empty<string>(),
|
||||
ExtraAotOptions = (string[])ProjectSettings.GetSetting("mono/export/aot/extra_aot_options") ??
|
||||
Array.Empty<string>(),
|
||||
ExtraOptimizerOptions =
|
||||
(string[])ProjectSettings.GetSetting("mono/export/aot/extra_optimizer_options") ??
|
||||
Array.Empty<string>(),
|
||||
ToolchainPath = aotToolchainPath
|
||||
};
|
||||
|
||||
AotBuilder.CompileAssemblies(this, aotOpts, features, platform, isDebug, bclDir, outputDir, outputDataDir, assemblies);
|
||||
AotBuilder.CompileAssemblies(this, aotOpts, features, platform, isDebug, bclDir, outputDir,
|
||||
outputDataDir, assemblies);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,7 +339,9 @@ namespace GodotTools.Export
|
|||
Directory.Delete(aotTempDir, recursive: true);
|
||||
|
||||
// TODO: Just a workaround until the export plugins can be made to abort with errors
|
||||
if (!string.IsNullOrEmpty(maybeLastExportError)) // Check empty as well, because it's set to empty after hot-reloading
|
||||
if (
|
||||
!string.IsNullOrEmpty(
|
||||
maybeLastExportError)) // Check empty as well, because it's set to empty after hot-reloading
|
||||
{
|
||||
string lastExportError = maybeLastExportError;
|
||||
maybeLastExportError = null;
|
||||
|
@ -326,7 +350,7 @@ namespace GodotTools.Export
|
|||
}
|
||||
}
|
||||
|
||||
[NotNull]
|
||||
[return: NotNull]
|
||||
private static string ExportDataDirectory(string[] features, string platform, bool isDebug, string outputDir)
|
||||
{
|
||||
string target = isDebug ? "release_debug" : "release";
|
||||
|
@ -381,7 +405,8 @@ namespace GodotTools.Export
|
|||
private static bool PlatformHasTemplateDir(string platform)
|
||||
{
|
||||
// OSX export templates are contained in a zip, so we place our custom template inside it and let Godot do the rest.
|
||||
return !new[] { OS.Platforms.MacOS, OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5 }.Contains(platform);
|
||||
return !new[] { OS.Platforms.MacOS, OS.Platforms.Android, OS.Platforms.iOS, OS.Platforms.HTML5 }
|
||||
.Contains(platform);
|
||||
}
|
||||
|
||||
private static bool DeterminePlatformFromFeatures(IEnumerable<string> features, out string platform)
|
||||
|
@ -474,9 +499,5 @@ namespace GodotTools.Export
|
|||
string appNameSafe = appName.ToSafeDirName();
|
||||
return $"data_{appNameSafe}";
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern void internal_GetExportedAssemblyDependencies(Godot.Collections.Dictionary<string, string> initialAssemblies,
|
||||
string buildConfig, string customBclDir, Godot.Collections.Dictionary<string, string> dependencyAssemblies);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,9 +50,10 @@ namespace GodotTools
|
|||
}
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
private bool CreateProjectSolution()
|
||||
{
|
||||
using (var pr = new EditorProgress("create_csharp_solution", "Generating solution...".TTR(), 3))
|
||||
using (var pr = new EditorProgress("create_csharp_solution", "Generating solution...".TTR(), 2))
|
||||
{
|
||||
pr.Step("Generating C# project...".TTR());
|
||||
|
||||
|
@ -89,24 +90,6 @@ namespace GodotTools
|
|||
return false;
|
||||
}
|
||||
|
||||
pr.Step("Updating Godot API assemblies...".TTR());
|
||||
|
||||
string debugApiAssembliesError = Internal.UpdateApiAssembliesFromPrebuilt("Debug");
|
||||
|
||||
if (!string.IsNullOrEmpty(debugApiAssembliesError))
|
||||
{
|
||||
ShowErrorDialog("Failed to update the Godot API assemblies: " + debugApiAssembliesError);
|
||||
return false;
|
||||
}
|
||||
|
||||
string releaseApiAssembliesError = Internal.UpdateApiAssembliesFromPrebuilt("Release");
|
||||
|
||||
if (!string.IsNullOrEmpty(releaseApiAssembliesError))
|
||||
{
|
||||
ShowErrorDialog("Failed to update the Godot API assemblies: " + releaseApiAssembliesError);
|
||||
return false;
|
||||
}
|
||||
|
||||
pr.Step("Done".TTR());
|
||||
|
||||
// Here, after all calls to progress_task_step
|
||||
|
@ -140,7 +123,8 @@ namespace GodotTools
|
|||
try
|
||||
{
|
||||
string fallbackFolder = NuGetUtils.GodotFallbackFolderPath;
|
||||
NuGetUtils.AddFallbackFolderToUserNuGetConfigs(NuGetUtils.GodotFallbackFolderName, fallbackFolder);
|
||||
NuGetUtils.AddFallbackFolderToUserNuGetConfigs(NuGetUtils.GodotFallbackFolderName,
|
||||
fallbackFolder);
|
||||
NuGetUtils.AddBundledPackagesToFallbackFolder(fallbackFolder);
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -218,13 +202,15 @@ namespace GodotTools
|
|||
try
|
||||
{
|
||||
if (Godot.OS.IsStdoutVerbose())
|
||||
Console.WriteLine($"Running: \"{command}\" {string.Join(" ", args.Select(a => $"\"{a}\""))}");
|
||||
Console.WriteLine(
|
||||
$"Running: \"{command}\" {string.Join(" ", args.Select(a => $"\"{a}\""))}");
|
||||
|
||||
OS.RunProcess(command, args);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
GD.PushError($"Error when trying to run code editor: VisualStudio. Exception message: '{e.Message}'");
|
||||
GD.PushError(
|
||||
$"Error when trying to run code editor: VisualStudio. Exception message: '{e.Message}'");
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -395,6 +381,8 @@ namespace GodotTools
|
|||
{
|
||||
base._EnablePlugin();
|
||||
|
||||
ProjectUtils.MSBuildLocatorRegisterDefaults();
|
||||
|
||||
if (Instance != null)
|
||||
throw new InvalidOperationException();
|
||||
Instance = this;
|
||||
|
@ -482,7 +470,8 @@ namespace GodotTools
|
|||
try
|
||||
{
|
||||
// At startup we make sure NuGet.Config files have our Godot NuGet fallback folder included
|
||||
NuGetUtils.AddFallbackFolderToUserNuGetConfigs(NuGetUtils.GodotFallbackFolderName, NuGetUtils.GodotFallbackFolderPath);
|
||||
NuGetUtils.AddFallbackFolderToUserNuGetConfigs(NuGetUtils.GodotFallbackFolderName,
|
||||
NuGetUtils.GodotFallbackFolderPath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -528,8 +517,9 @@ namespace GodotTools
|
|||
public static GodotSharpEditor Instance { get; private set; }
|
||||
|
||||
[UsedImplicitly]
|
||||
private GodotSharpEditor()
|
||||
private static IntPtr InternalCreateInstance()
|
||||
{
|
||||
return new GodotSharpEditor().NativeInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{27B00618-A6F2-4828-B922-05CAEB08C286}</ProjectGuid>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<LangVersion>7.2</LangVersion>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<EnableDynamicLoading>true</EnableDynamicLoading>
|
||||
<LangVersion>8</LangVersion>
|
||||
<!-- The Godot editor uses the Debug Godot API assemblies -->
|
||||
<GodotApiConfiguration>Debug</GodotApiConfiguration>
|
||||
<GodotSourceRootPath>$(SolutionDir)/../../../../</GodotSourceRootPath>
|
||||
<GodotOutputDataDir>$(GodotSourceRootPath)/bin/GodotSharp</GodotOutputDataDir>
|
||||
<GodotApiAssembliesDir>$(GodotOutputDataDir)/Api/$(GodotApiConfiguration)</GodotApiAssembliesDir>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" Exists('$(GodotApiAssembliesDir)/GodotSharp.dll') ">
|
||||
<!-- The project is part of the Godot source tree -->
|
||||
|
@ -20,6 +22,8 @@
|
|||
<PackageReference Include="JetBrains.Annotations" Version="2019.1.3.0" ExcludeAssets="runtime" PrivateAssets="all" />
|
||||
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0" PrivateAssets="All" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||
<!-- For RiderPathLocator -->
|
||||
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
|
||||
<Reference Include="GodotSharp">
|
||||
<HintPath>$(GodotApiAssembliesDir)/GodotSharp.dll</HintPath>
|
||||
<Private>False</Private>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using Godot;
|
||||
using GodotTools.Internals;
|
||||
using JetBrains.Annotations;
|
||||
using static GodotTools.Internals.Globals;
|
||||
|
||||
namespace GodotTools
|
||||
|
@ -25,6 +26,7 @@ namespace GodotTools
|
|||
Internal.ReloadAssemblies(softReload: false);
|
||||
}
|
||||
|
||||
[UsedImplicitly]
|
||||
public void RestartTimer()
|
||||
{
|
||||
watchTimer.Stop();
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.Versioning;
|
||||
using Godot;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.Win32;
|
||||
using Newtonsoft.Json;
|
||||
using Directory = System.IO.Directory;
|
||||
|
@ -112,6 +113,7 @@ namespace GodotTools.Ides.Rider
|
|||
return installInfos.ToArray();
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
private static RiderInfo[] CollectRiderInfosWindows()
|
||||
{
|
||||
var installInfos = new List<RiderInfo>();
|
||||
|
@ -216,6 +218,7 @@ namespace GodotTools.Ides.Rider
|
|||
throw new Exception("Unknown OS.");
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
private static void CollectPathsFromRegistry(string registryKey, List<string> installPaths)
|
||||
{
|
||||
using (var key = Registry.CurrentUser.OpenSubKey(registryKey))
|
||||
|
@ -228,6 +231,7 @@ namespace GodotTools.Ides.Rider
|
|||
}
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
private static void CollectPathsFromRegistry(List<string> installPaths, RegistryKey key)
|
||||
{
|
||||
if (key == null) return;
|
||||
|
@ -323,7 +327,7 @@ namespace GodotTools.Ides.Rider
|
|||
{
|
||||
public string install_location;
|
||||
|
||||
[CanBeNull]
|
||||
[return: MaybeNull]
|
||||
public static string GetInstallLocationFromJson(string json)
|
||||
{
|
||||
try
|
||||
|
@ -377,7 +381,7 @@ namespace GodotTools.Ides.Rider
|
|||
public string version;
|
||||
public string versionSuffix;
|
||||
|
||||
[CanBeNull]
|
||||
[return: MaybeNull]
|
||||
internal static ProductInfo GetProductInfo(string json)
|
||||
{
|
||||
try
|
||||
|
@ -401,7 +405,7 @@ namespace GodotTools.Ides.Rider
|
|||
// ReSharper disable once InconsistentNaming
|
||||
public ActiveApplication active_application;
|
||||
|
||||
[CanBeNull]
|
||||
[return: MaybeNull]
|
||||
public static string GetLatestBuildFromJson(string json)
|
||||
{
|
||||
try
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Godot;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
namespace GodotTools.Internals
|
||||
{
|
||||
|
@ -8,19 +9,12 @@ namespace GodotTools.Internals
|
|||
{
|
||||
public string Task { get; }
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern void internal_Create(string task, string label, int amount, bool canCancel);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern void internal_Dispose(string task);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern bool internal_Step(string task, string state, int step, bool forceRefresh);
|
||||
|
||||
public EditorProgress(string task, string label, int amount, bool canCancel = false)
|
||||
{
|
||||
Task = task;
|
||||
internal_Create(task, label, amount, canCancel);
|
||||
using godot_string taskIn = Marshaling.mono_string_to_godot(task);
|
||||
using godot_string labelIn = Marshaling.mono_string_to_godot(label);
|
||||
Internal.godot_icall_EditorProgress_Create(taskIn, labelIn, amount, canCancel);
|
||||
}
|
||||
|
||||
~EditorProgress()
|
||||
|
@ -33,18 +27,23 @@ namespace GodotTools.Internals
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
internal_Dispose(Task);
|
||||
using godot_string taskIn = Marshaling.mono_string_to_godot(Task);
|
||||
Internal.godot_icall_EditorProgress_Dispose(taskIn);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public void Step(string state, int step = -1, bool forceRefresh = true)
|
||||
{
|
||||
internal_Step(Task, state, step, forceRefresh);
|
||||
using godot_string taskIn = Marshaling.mono_string_to_godot(Task);
|
||||
using godot_string stateIn = Marshaling.mono_string_to_godot(state);
|
||||
Internal.godot_icall_EditorProgress_Step(taskIn, stateIn, step, forceRefresh);
|
||||
}
|
||||
|
||||
public bool TryStep(string state, int step = -1, bool forceRefresh = true)
|
||||
{
|
||||
return internal_Step(Task, state, step, forceRefresh);
|
||||
using godot_string taskIn = Marshaling.mono_string_to_godot(Task);
|
||||
using godot_string stateIn = Marshaling.mono_string_to_godot(state);
|
||||
return Internal.godot_icall_EditorProgress_Step(taskIn, stateIn, step, forceRefresh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
using Godot.NativeInterop;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
|
@ -5,29 +6,33 @@ namespace GodotTools.Internals
|
|||
{
|
||||
public static class Globals
|
||||
{
|
||||
public static float EditorScale => internal_EditorScale();
|
||||
public static float EditorScale => Internal.godot_icall_Globals_EditorScale();
|
||||
|
||||
public static object GlobalDef(string setting, object defaultValue, bool restartIfChanged = false) =>
|
||||
internal_GlobalDef(setting, defaultValue, restartIfChanged);
|
||||
public static unsafe object GlobalDef(string setting, object defaultValue, bool restartIfChanged = false)
|
||||
{
|
||||
using godot_string settingIn = Marshaling.mono_string_to_godot(setting);
|
||||
using godot_variant defaultValueIn = Marshaling.mono_object_to_variant(defaultValue);
|
||||
Internal.godot_icall_Globals_GlobalDef(settingIn, defaultValueIn, restartIfChanged, out godot_variant result);
|
||||
using (result)
|
||||
return Marshaling.variant_to_mono_object(&result);
|
||||
}
|
||||
|
||||
public static object EditorDef(string setting, object defaultValue, bool restartIfChanged = false) =>
|
||||
internal_EditorDef(setting, defaultValue, restartIfChanged);
|
||||
public static unsafe object EditorDef(string setting, object defaultValue, bool restartIfChanged = false)
|
||||
{
|
||||
using godot_string settingIn = Marshaling.mono_string_to_godot(setting);
|
||||
using godot_variant defaultValueIn = Marshaling.mono_object_to_variant(defaultValue);
|
||||
Internal.godot_icall_Globals_EditorDef(settingIn, defaultValueIn, restartIfChanged, out godot_variant result);
|
||||
using (result)
|
||||
return Marshaling.variant_to_mono_object(&result);
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public static string TTR(this string text) => internal_TTR(text);
|
||||
|
||||
// Internal Calls
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern float internal_EditorScale();
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern object internal_GlobalDef(string setting, object defaultValue, bool restartIfChanged);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern object internal_EditorDef(string setting, object defaultValue, bool restartIfChanged);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_TTR(string text);
|
||||
public static string TTR(this string text)
|
||||
{
|
||||
using godot_string textIn = Marshaling.mono_string_to_godot(text);
|
||||
Internal.godot_icall_Globals_TTR(textIn, out godot_string dest);
|
||||
using (dest)
|
||||
return Marshaling.mono_string_from_godot(dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,91 +1,78 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
namespace GodotTools.Internals
|
||||
{
|
||||
public static class GodotSharpDirs
|
||||
{
|
||||
public static string ResDataDir => internal_ResDataDir();
|
||||
public static string ResMetadataDir => internal_ResMetadataDir();
|
||||
public static string ResAssembliesBaseDir => internal_ResAssembliesBaseDir();
|
||||
public static string ResAssembliesDir => internal_ResAssembliesDir();
|
||||
public static string ResConfigDir => internal_ResConfigDir();
|
||||
public static string ResTempDir => internal_ResTempDir();
|
||||
public static string ResTempAssembliesBaseDir => internal_ResTempAssembliesBaseDir();
|
||||
public static string ResTempAssembliesDir => internal_ResTempAssembliesDir();
|
||||
|
||||
public static string MonoUserDir => internal_MonoUserDir();
|
||||
public static string MonoLogsDir => internal_MonoLogsDir();
|
||||
|
||||
#region Tools-only
|
||||
public static string MonoSolutionsDir => internal_MonoSolutionsDir();
|
||||
public static string BuildLogsDirs => internal_BuildLogsDirs();
|
||||
|
||||
public static string ProjectSlnPath => internal_ProjectSlnPath();
|
||||
public static string ProjectCsProjPath => internal_ProjectCsProjPath();
|
||||
|
||||
public static string DataEditorToolsDir => internal_DataEditorToolsDir();
|
||||
public static string DataEditorPrebuiltApiDir => internal_DataEditorPrebuiltApiDir();
|
||||
#endregion
|
||||
|
||||
public static string DataMonoEtcDir => internal_DataMonoEtcDir();
|
||||
public static string DataMonoLibDir => internal_DataMonoLibDir();
|
||||
|
||||
#region Windows-only
|
||||
public static string DataMonoBinDir => internal_DataMonoBinDir();
|
||||
#endregion
|
||||
|
||||
|
||||
#region Internal
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_ResDataDir();
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_ResMetadataDir();
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_ResAssembliesBaseDir();
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_ResAssembliesDir();
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_ResConfigDir();
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_ResTempDir();
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_ResTempAssembliesBaseDir();
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_ResTempAssembliesDir();
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_MonoUserDir();
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_MonoLogsDir();
|
||||
|
||||
#region Tools-only
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_MonoSolutionsDir();
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_BuildLogsDirs();
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_ProjectSlnPath();
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_ProjectCsProjPath();
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_DataEditorToolsDir();
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_DataEditorPrebuiltApiDir();
|
||||
#endregion
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_DataMonoEtcDir();
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_DataMonoLibDir();
|
||||
|
||||
#region Windows-only
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_DataMonoBinDir();
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
public static string ResMetadataDir
|
||||
{
|
||||
get
|
||||
{
|
||||
Internal.godot_icall_GodotSharpDirs_ResMetadataDir(out godot_string dest);
|
||||
using (dest)
|
||||
return Marshaling.mono_string_from_godot(dest);
|
||||
}
|
||||
}
|
||||
|
||||
public static string ResTempAssembliesBaseDir
|
||||
{
|
||||
get
|
||||
{
|
||||
Internal.godot_icall_GodotSharpDirs_ResTempAssembliesBaseDir(out godot_string dest);
|
||||
using (dest)
|
||||
return Marshaling.mono_string_from_godot(dest);
|
||||
}
|
||||
}
|
||||
|
||||
public static string MonoUserDir
|
||||
{
|
||||
get
|
||||
{
|
||||
Internal.godot_icall_GodotSharpDirs_MonoUserDir(out godot_string dest);
|
||||
using (dest)
|
||||
return Marshaling.mono_string_from_godot(dest);
|
||||
}
|
||||
}
|
||||
|
||||
public static string BuildLogsDirs
|
||||
{
|
||||
get
|
||||
{
|
||||
Internal.godot_icall_GodotSharpDirs_BuildLogsDirs(out godot_string dest);
|
||||
using (dest)
|
||||
return Marshaling.mono_string_from_godot(dest);
|
||||
}
|
||||
}
|
||||
|
||||
public static string ProjectSlnPath
|
||||
{
|
||||
get
|
||||
{
|
||||
Internal.godot_icall_GodotSharpDirs_ProjectSlnPath(out godot_string dest);
|
||||
using (dest)
|
||||
return Marshaling.mono_string_from_godot(dest);
|
||||
}
|
||||
}
|
||||
|
||||
public static string ProjectCsProjPath
|
||||
{
|
||||
get
|
||||
{
|
||||
Internal.godot_icall_GodotSharpDirs_ProjectCsProjPath(out godot_string dest);
|
||||
using (dest)
|
||||
return Marshaling.mono_string_from_godot(dest);
|
||||
}
|
||||
}
|
||||
|
||||
public static string DataEditorToolsDir
|
||||
{
|
||||
get
|
||||
{
|
||||
Internal.godot_icall_GodotSharpDirs_DataEditorToolsDir(out godot_string dest);
|
||||
using (dest)
|
||||
return Marshaling.mono_string_from_godot(dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,114 +1,189 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Godot;
|
||||
using Godot.NativeInterop;
|
||||
using GodotTools.IdeMessaging.Requests;
|
||||
|
||||
namespace GodotTools.Internals
|
||||
{
|
||||
public static class Internal
|
||||
internal static class Internal
|
||||
{
|
||||
public const string CSharpLanguageType = "CSharpScript";
|
||||
public const string CSharpLanguageExtension = ".cs";
|
||||
|
||||
public static string UpdateApiAssembliesFromPrebuilt(string config) =>
|
||||
internal_UpdateApiAssembliesFromPrebuilt(config);
|
||||
public static string FullTemplatesDir
|
||||
{
|
||||
get
|
||||
{
|
||||
godot_icall_Internal_FullTemplatesDir(out godot_string dest);
|
||||
using (dest)
|
||||
return Marshaling.mono_string_from_godot(dest);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FullTemplatesDir =>
|
||||
internal_FullTemplatesDir();
|
||||
public static string SimplifyGodotPath(this string path)
|
||||
{
|
||||
using godot_string pathIn = Marshaling.mono_string_to_godot(path);
|
||||
godot_icall_Internal_SimplifyGodotPath(pathIn, out godot_string dest);
|
||||
using (dest)
|
||||
return Marshaling.mono_string_from_godot(dest);
|
||||
}
|
||||
|
||||
public static string SimplifyGodotPath(this string path) => internal_SimplifyGodotPath(path);
|
||||
public static bool IsOsxAppBundleInstalled(string bundleId)
|
||||
{
|
||||
using godot_string bundleIdIn = Marshaling.mono_string_to_godot(bundleId);
|
||||
return godot_icall_Internal_IsOsxAppBundleInstalled(bundleIdIn);
|
||||
}
|
||||
|
||||
public static bool IsOsxAppBundleInstalled(string bundleId) => internal_IsOsxAppBundleInstalled(bundleId);
|
||||
public static bool GodotIs32Bits() => godot_icall_Internal_GodotIs32Bits();
|
||||
|
||||
public static bool GodotIs32Bits() => internal_GodotIs32Bits();
|
||||
public static bool GodotIsRealTDouble() => godot_icall_Internal_GodotIsRealTDouble();
|
||||
|
||||
public static bool GodotIsRealTDouble() => internal_GodotIsRealTDouble();
|
||||
public static void GodotMainIteration() => godot_icall_Internal_GodotMainIteration();
|
||||
|
||||
public static void GodotMainIteration() => internal_GodotMainIteration();
|
||||
public static bool IsAssembliesReloadingNeeded() => godot_icall_Internal_IsAssembliesReloadingNeeded();
|
||||
|
||||
public static ulong GetCoreApiHash() => internal_GetCoreApiHash();
|
||||
public static void ReloadAssemblies(bool softReload) => godot_icall_Internal_ReloadAssemblies(softReload);
|
||||
|
||||
public static ulong GetEditorApiHash() => internal_GetEditorApiHash();
|
||||
|
||||
public static bool IsAssembliesReloadingNeeded() => internal_IsAssembliesReloadingNeeded();
|
||||
|
||||
public static void ReloadAssemblies(bool softReload) => internal_ReloadAssemblies(softReload);
|
||||
|
||||
public static void EditorDebuggerNodeReloadScripts() => internal_EditorDebuggerNodeReloadScripts();
|
||||
public static void EditorDebuggerNodeReloadScripts() => godot_icall_Internal_EditorDebuggerNodeReloadScripts();
|
||||
|
||||
public static bool ScriptEditorEdit(Resource resource, int line, int col, bool grabFocus = true) =>
|
||||
internal_ScriptEditorEdit(resource, line, col, grabFocus);
|
||||
godot_icall_Internal_ScriptEditorEdit(resource.NativeInstance, line, col, grabFocus);
|
||||
|
||||
public static void EditorNodeShowScriptScreen() => internal_EditorNodeShowScriptScreen();
|
||||
public static void EditorNodeShowScriptScreen() => godot_icall_Internal_EditorNodeShowScriptScreen();
|
||||
|
||||
public static string MonoWindowsInstallRoot => internal_MonoWindowsInstallRoot();
|
||||
public static string MonoWindowsInstallRoot
|
||||
{
|
||||
get
|
||||
{
|
||||
godot_icall_Internal_MonoWindowsInstallRoot(out godot_string dest);
|
||||
using (dest)
|
||||
return Marshaling.mono_string_from_godot(dest);
|
||||
}
|
||||
}
|
||||
|
||||
public static void EditorRunPlay() => internal_EditorRunPlay();
|
||||
public static void EditorRunPlay() => godot_icall_Internal_EditorRunPlay();
|
||||
|
||||
public static void EditorRunStop() => internal_EditorRunStop();
|
||||
public static void EditorRunStop() => godot_icall_Internal_EditorRunStop();
|
||||
|
||||
public static void ScriptEditorDebugger_ReloadScripts() => internal_ScriptEditorDebugger_ReloadScripts();
|
||||
public static void ScriptEditorDebugger_ReloadScripts() =>
|
||||
godot_icall_Internal_ScriptEditorDebugger_ReloadScripts();
|
||||
|
||||
public static string[] CodeCompletionRequest(CodeCompletionRequest.CompletionKind kind, string scriptFile) =>
|
||||
internal_CodeCompletionRequest((int)kind, scriptFile);
|
||||
public static unsafe string[] CodeCompletionRequest(CodeCompletionRequest.CompletionKind kind,
|
||||
string scriptFile)
|
||||
{
|
||||
using godot_string scriptFileIn = Marshaling.mono_string_to_godot(scriptFile);
|
||||
godot_icall_Internal_CodeCompletionRequest((int)kind, scriptFileIn, out godot_packed_string_array res);
|
||||
using (res)
|
||||
return Marshaling.PackedStringArray_to_mono_array(&res);
|
||||
}
|
||||
|
||||
#region Internal
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_UpdateApiAssembliesFromPrebuilt(string config);
|
||||
private const string GodotDllName = "__Internal";
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_FullTemplatesDir();
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godot_icall_GodotSharpDirs_ResMetadataDir(out godot_string r_dest);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_SimplifyGodotPath(this string path);
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godot_icall_GodotSharpDirs_ResTempAssembliesBaseDir(out godot_string r_dest);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern bool internal_IsOsxAppBundleInstalled(string bundleId);
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godot_icall_GodotSharpDirs_MonoUserDir(out godot_string r_dest);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern bool internal_GodotIs32Bits();
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godot_icall_GodotSharpDirs_BuildLogsDirs(out godot_string r_dest);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern bool internal_GodotIsRealTDouble();
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godot_icall_GodotSharpDirs_ProjectSlnPath(out godot_string r_dest);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern void internal_GodotMainIteration();
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godot_icall_GodotSharpDirs_ProjectCsProjPath(out godot_string r_dest);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern ulong internal_GetCoreApiHash();
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godot_icall_GodotSharpDirs_DataEditorToolsDir(out godot_string r_dest);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern ulong internal_GetEditorApiHash();
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godot_icall_EditorProgress_Create(in godot_string task, in godot_string label,
|
||||
int amount, bool canCancel);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern bool internal_IsAssembliesReloadingNeeded();
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godot_icall_EditorProgress_Dispose(in godot_string task);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern void internal_ReloadAssemblies(bool softReload);
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern bool godot_icall_EditorProgress_Step(in godot_string task, in godot_string state, int step,
|
||||
bool forceRefresh);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern void internal_EditorDebuggerNodeReloadScripts();
|
||||
[DllImport(GodotDllName)]
|
||||
private static extern void godot_icall_Internal_FullTemplatesDir(out godot_string dest);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern bool internal_ScriptEditorEdit(Resource resource, int line, int col, bool grabFocus);
|
||||
[DllImport(GodotDllName)]
|
||||
private static extern void godot_icall_Internal_SimplifyGodotPath(in godot_string path, out godot_string dest);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern void internal_EditorNodeShowScriptScreen();
|
||||
[DllImport(GodotDllName)]
|
||||
private static extern bool godot_icall_Internal_IsOsxAppBundleInstalled(in godot_string bundleId);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string internal_MonoWindowsInstallRoot();
|
||||
[DllImport(GodotDllName)]
|
||||
private static extern bool godot_icall_Internal_GodotIs32Bits();
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern void internal_EditorRunPlay();
|
||||
[DllImport(GodotDllName)]
|
||||
private static extern bool godot_icall_Internal_GodotIsRealTDouble();
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern void internal_EditorRunStop();
|
||||
[DllImport(GodotDllName)]
|
||||
private static extern void godot_icall_Internal_GodotMainIteration();
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern void internal_ScriptEditorDebugger_ReloadScripts();
|
||||
[DllImport(GodotDllName)]
|
||||
private static extern bool godot_icall_Internal_IsAssembliesReloadingNeeded();
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string[] internal_CodeCompletionRequest(int kind, string scriptFile);
|
||||
[DllImport(GodotDllName)]
|
||||
private static extern void godot_icall_Internal_ReloadAssemblies(bool softReload);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
private static extern void godot_icall_Internal_EditorDebuggerNodeReloadScripts();
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
private static extern bool godot_icall_Internal_ScriptEditorEdit(IntPtr resource, int line, int col,
|
||||
bool grabFocus);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
private static extern void godot_icall_Internal_EditorNodeShowScriptScreen();
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
private static extern void godot_icall_Internal_MonoWindowsInstallRoot(out godot_string dest);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
private static extern void godot_icall_Internal_EditorRunPlay();
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
private static extern void godot_icall_Internal_EditorRunStop();
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
private static extern void godot_icall_Internal_ScriptEditorDebugger_ReloadScripts();
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
private static extern void godot_icall_Internal_CodeCompletionRequest(int kind, in godot_string scriptFile,
|
||||
out godot_packed_string_array res);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern float godot_icall_Globals_EditorScale();
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godot_icall_Globals_GlobalDef(in godot_string setting, in godot_variant defaultValue,
|
||||
bool restartIfChanged, out godot_variant result);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godot_icall_Globals_EditorDef(in godot_string setting, in godot_variant defaultValue,
|
||||
bool restartIfChanged, out godot_variant result);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godot_icall_Globals_TTR(in godot_string text, out godot_string dest);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godot_icall_Utils_OS_GetPlatformName(out godot_string dest);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern bool godot_icall_Utils_OS_UnixFileHasExecutableAccess(in godot_string filePath);
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using Godot;
|
||||
using GodotTools.Core;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace GodotTools.Utils
|
||||
{
|
||||
|
@ -30,7 +30,7 @@ namespace GodotTools.Utils
|
|||
return childPathNorm.PathStartsWithAlreadyNorm(parentPathNorm);
|
||||
}
|
||||
|
||||
[CanBeNull]
|
||||
[return: MaybeNull]
|
||||
public static string LocalizePathWithCaseChecked(string path)
|
||||
{
|
||||
string pathNorm = path.NormalizePath() + Path.DirectorySeparatorChar;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
using Godot.NativeInterop;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
@ -5,19 +6,13 @@ using System.Diagnostics.CodeAnalysis;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using JetBrains.Annotations;
|
||||
using GodotTools.Internals;
|
||||
|
||||
namespace GodotTools.Utils
|
||||
{
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public static class OS
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
static extern string GetPlatformName();
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
static extern bool UnixFileHasExecutableAccess(string filePath);
|
||||
|
||||
public static class Names
|
||||
{
|
||||
public const string Windows = "Windows";
|
||||
|
@ -63,14 +58,24 @@ namespace GodotTools.Utils
|
|||
[Names.HTML5] = Platforms.HTML5
|
||||
};
|
||||
|
||||
private static bool IsOS(string name)
|
||||
private static unsafe bool IsOS(string name)
|
||||
{
|
||||
return name.Equals(GetPlatformName(), StringComparison.OrdinalIgnoreCase);
|
||||
Internal.godot_icall_Utils_OS_GetPlatformName(out godot_string dest);
|
||||
using (dest)
|
||||
{
|
||||
string platformName = Marshaling.mono_string_from_godot(dest);
|
||||
return name.Equals(platformName, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsAnyOS(IEnumerable<string> names)
|
||||
private static unsafe bool IsAnyOS(IEnumerable<string> names)
|
||||
{
|
||||
return names.Any(p => p.Equals(GetPlatformName(), StringComparison.OrdinalIgnoreCase));
|
||||
Internal.godot_icall_Utils_OS_GetPlatformName(out godot_string dest);
|
||||
using (dest)
|
||||
{
|
||||
string platformName = Marshaling.mono_string_from_godot(dest);
|
||||
return names.Any(p => p.Equals(platformName, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly IEnumerable<string> LinuxBSDPlatforms =
|
||||
|
@ -91,14 +96,23 @@ namespace GodotTools.Utils
|
|||
private static readonly Lazy<bool> _isHTML5 = new Lazy<bool>(() => IsOS(Names.HTML5));
|
||||
private static readonly Lazy<bool> _isUnixLike = new Lazy<bool>(() => IsAnyOS(UnixLikePlatforms));
|
||||
|
||||
// TODO SupportedOSPlatformGuard once we target .NET 6
|
||||
// [SupportedOSPlatformGuard("windows")]
|
||||
public static bool IsWindows => _isWindows.Value || IsUWP;
|
||||
// [SupportedOSPlatformGuard("osx")]
|
||||
public static bool IsMacOS => _isMacOS.Value;
|
||||
// [SupportedOSPlatformGuard("linux")]
|
||||
public static bool IsLinuxBSD => _isLinuxBSD.Value;
|
||||
// [SupportedOSPlatformGuard("linux")]
|
||||
public static bool IsServer => _isServer.Value;
|
||||
// [SupportedOSPlatformGuard("windows")]
|
||||
public static bool IsUWP => _isUWP.Value;
|
||||
public static bool IsHaiku => _isHaiku.Value;
|
||||
// [SupportedOSPlatformGuard("android")]
|
||||
public static bool IsAndroid => _isAndroid.Value;
|
||||
// [SupportedOSPlatformGuard("ios")]
|
||||
public static bool IsiOS => _isiOS.Value;
|
||||
// [SupportedOSPlatformGuard("browser")]
|
||||
public static bool IsHTML5 => _isHTML5.Value;
|
||||
public static bool IsUnixLike => _isUnixLike.Value;
|
||||
|
||||
|
@ -111,7 +125,8 @@ namespace GodotTools.Utils
|
|||
|
||||
private static string PathWhichWindows([NotNull] string name)
|
||||
{
|
||||
string[] windowsExts = Environment.GetEnvironmentVariable("PATHEXT")?.Split(PathSep) ?? Array.Empty<string>();
|
||||
string[] windowsExts =
|
||||
Environment.GetEnvironmentVariable("PATHEXT")?.Split(PathSep) ?? Array.Empty<string>();
|
||||
string[] pathDirs = Environment.GetEnvironmentVariable("PATH")?.Split(PathSep);
|
||||
char[] invalidPathChars = Path.GetInvalidPathChars();
|
||||
|
||||
|
@ -129,7 +144,8 @@ namespace GodotTools.Utils
|
|||
}
|
||||
|
||||
string nameExt = Path.GetExtension(name);
|
||||
bool hasPathExt = !string.IsNullOrEmpty(nameExt) && windowsExts.Contains(nameExt, StringComparer.OrdinalIgnoreCase);
|
||||
bool hasPathExt = !string.IsNullOrEmpty(nameExt) &&
|
||||
windowsExts.Contains(nameExt, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
searchDirs.Add(System.IO.Directory.GetCurrentDirectory()); // last in the list
|
||||
|
||||
|
@ -164,7 +180,11 @@ namespace GodotTools.Utils
|
|||
searchDirs.Add(System.IO.Directory.GetCurrentDirectory()); // last in the list
|
||||
|
||||
return searchDirs.Select(dir => Path.Combine(dir, name))
|
||||
.FirstOrDefault(path => File.Exists(path) && UnixFileHasExecutableAccess(path));
|
||||
.FirstOrDefault(path =>
|
||||
{
|
||||
using godot_string pathIn = Marshaling.mono_string_to_godot(path);
|
||||
return File.Exists(path) && Internal.godot_icall_Utils_OS_UnixFileHasExecutableAccess(pathIn);
|
||||
});
|
||||
}
|
||||
|
||||
public static void RunProcess(string command, IEnumerable<string> arguments)
|
||||
|
|
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;
|
||||
|
@ -356,6 +358,8 @@ class BindingsGenerator {
|
|||
List<MethodInterface> methods;
|
||||
List<SignalInterface> signals_;
|
||||
|
||||
bool has_virtual_methods = false;
|
||||
|
||||
const MethodInterface *find_method_by_name(const StringName &p_cname) const {
|
||||
for (const MethodInterface &E : methods) {
|
||||
if (E.cname == p_cname) {
|
||||
|
@ -402,8 +406,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 +441,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 +475,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 +482,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 +496,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 +563,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 +573,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 +584,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 +623,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 +638,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,179 +43,120 @@
|
|||
#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"
|
||||
#include "code_completion.h"
|
||||
#include "godotsharp_export.h"
|
||||
|
||||
MonoString *godot_icall_GodotSharpDirs_ResDataDir() {
|
||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_res_data_dir());
|
||||
#include <gdnative/gdnative.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
|
||||
|
||||
void godot_icall_GodotSharpDirs_ResMetadataDir(godot_string *r_dest) {
|
||||
memnew_placement(r_dest, String(GodotSharpDirs::get_res_metadata_dir()));
|
||||
}
|
||||
|
||||
MonoString *godot_icall_GodotSharpDirs_ResMetadataDir() {
|
||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_res_metadata_dir());
|
||||
void godot_icall_GodotSharpDirs_ResTempAssembliesBaseDir(godot_string *r_dest) {
|
||||
memnew_placement(r_dest, String(GodotSharpDirs::get_res_temp_assemblies_base_dir()));
|
||||
}
|
||||
|
||||
MonoString *godot_icall_GodotSharpDirs_ResAssembliesBaseDir() {
|
||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_res_assemblies_base_dir());
|
||||
void godot_icall_GodotSharpDirs_MonoUserDir(godot_string *r_dest) {
|
||||
memnew_placement(r_dest, String(GodotSharpDirs::get_mono_user_dir()));
|
||||
}
|
||||
|
||||
MonoString *godot_icall_GodotSharpDirs_ResAssembliesDir() {
|
||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_res_assemblies_dir());
|
||||
}
|
||||
|
||||
MonoString *godot_icall_GodotSharpDirs_ResConfigDir() {
|
||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_res_config_dir());
|
||||
}
|
||||
|
||||
MonoString *godot_icall_GodotSharpDirs_ResTempDir() {
|
||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_res_temp_dir());
|
||||
}
|
||||
|
||||
MonoString *godot_icall_GodotSharpDirs_ResTempAssembliesBaseDir() {
|
||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_res_temp_assemblies_base_dir());
|
||||
}
|
||||
|
||||
MonoString *godot_icall_GodotSharpDirs_ResTempAssembliesDir() {
|
||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_res_temp_assemblies_dir());
|
||||
}
|
||||
|
||||
MonoString *godot_icall_GodotSharpDirs_MonoUserDir() {
|
||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_mono_user_dir());
|
||||
}
|
||||
|
||||
MonoString *godot_icall_GodotSharpDirs_MonoLogsDir() {
|
||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_mono_logs_dir());
|
||||
}
|
||||
|
||||
MonoString *godot_icall_GodotSharpDirs_MonoSolutionsDir() {
|
||||
void godot_icall_GodotSharpDirs_BuildLogsDirs(godot_string *r_dest) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_mono_solutions_dir());
|
||||
memnew_placement(r_dest, String(GodotSharpDirs::get_build_logs_dir()));
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
MonoString *godot_icall_GodotSharpDirs_BuildLogsDirs() {
|
||||
void godot_icall_GodotSharpDirs_ProjectSlnPath(godot_string *r_dest) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_build_logs_dir());
|
||||
memnew_placement(r_dest, String(GodotSharpDirs::get_project_sln_path()));
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
MonoString *godot_icall_GodotSharpDirs_ProjectSlnPath() {
|
||||
void godot_icall_GodotSharpDirs_ProjectCsProjPath(godot_string *r_dest) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_project_sln_path());
|
||||
memnew_placement(r_dest, String(GodotSharpDirs::get_project_csproj_path()));
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
MonoString *godot_icall_GodotSharpDirs_ProjectCsProjPath() {
|
||||
void godot_icall_GodotSharpDirs_DataEditorToolsDir(godot_string *r_dest) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_project_csproj_path());
|
||||
memnew_placement(r_dest, String(GodotSharpDirs::get_data_editor_tools_dir()));
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
MonoString *godot_icall_GodotSharpDirs_DataEditorToolsDir() {
|
||||
#ifdef TOOLS_ENABLED
|
||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_data_editor_tools_dir());
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
MonoString *godot_icall_GodotSharpDirs_DataEditorPrebuiltApiDir() {
|
||||
#ifdef TOOLS_ENABLED
|
||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_data_editor_prebuilt_api_dir());
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
MonoString *godot_icall_GodotSharpDirs_DataMonoEtcDir() {
|
||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_data_mono_etc_dir());
|
||||
}
|
||||
|
||||
MonoString *godot_icall_GodotSharpDirs_DataMonoLibDir() {
|
||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_data_mono_lib_dir());
|
||||
}
|
||||
|
||||
MonoString *godot_icall_GodotSharpDirs_DataMonoBinDir() {
|
||||
#ifdef WINDOWS_ENABLED
|
||||
return GDMonoMarshal::mono_string_from_godot(GodotSharpDirs::get_data_mono_bin_dir());
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void godot_icall_EditorProgress_Create(MonoString *p_task, MonoString *p_label, int32_t p_amount, MonoBoolean p_can_cancel) {
|
||||
String task = GDMonoMarshal::mono_string_to_godot(p_task);
|
||||
String label = GDMonoMarshal::mono_string_to_godot(p_label);
|
||||
void godot_icall_EditorProgress_Create(const godot_string *p_task, const godot_string *p_label, int32_t p_amount, bool p_can_cancel) {
|
||||
String task = *reinterpret_cast<const String *>(p_task);
|
||||
String label = *reinterpret_cast<const String *>(p_label);
|
||||
EditorNode::progress_add_task(task, label, p_amount, (bool)p_can_cancel);
|
||||
}
|
||||
|
||||
void godot_icall_EditorProgress_Dispose(MonoString *p_task) {
|
||||
String task = GDMonoMarshal::mono_string_to_godot(p_task);
|
||||
void godot_icall_EditorProgress_Dispose(const godot_string *p_task) {
|
||||
String task = *reinterpret_cast<const String *>(p_task);
|
||||
EditorNode::progress_end_task(task);
|
||||
}
|
||||
|
||||
MonoBoolean godot_icall_EditorProgress_Step(MonoString *p_task, MonoString *p_state, int32_t p_step, MonoBoolean p_force_refresh) {
|
||||
String task = GDMonoMarshal::mono_string_to_godot(p_task);
|
||||
String state = GDMonoMarshal::mono_string_to_godot(p_state);
|
||||
bool godot_icall_EditorProgress_Step(const godot_string *p_task, const godot_string *p_state, int32_t p_step, bool p_force_refresh) {
|
||||
String task = *reinterpret_cast<const String *>(p_task);
|
||||
String state = *reinterpret_cast<const String *>(p_state);
|
||||
return EditorNode::progress_task_step(task, state, p_step, (bool)p_force_refresh);
|
||||
}
|
||||
|
||||
uint32_t godot_icall_ExportPlugin_GetExportedAssemblyDependencies(MonoObject *p_initial_assemblies,
|
||||
MonoString *p_build_config, MonoString *p_custom_bcl_dir, MonoObject *r_assembly_dependencies) {
|
||||
Dictionary initial_dependencies = GDMonoMarshal::mono_object_to_variant(p_initial_assemblies);
|
||||
String build_config = GDMonoMarshal::mono_string_to_godot(p_build_config);
|
||||
String custom_bcl_dir = GDMonoMarshal::mono_string_to_godot(p_custom_bcl_dir);
|
||||
Dictionary assembly_dependencies = GDMonoMarshal::mono_object_to_variant(r_assembly_dependencies);
|
||||
|
||||
return GodotSharpExport::get_exported_assembly_dependencies(initial_dependencies, build_config, custom_bcl_dir, assembly_dependencies);
|
||||
}
|
||||
|
||||
MonoString *godot_icall_Internal_UpdateApiAssembliesFromPrebuilt(MonoString *p_config) {
|
||||
String config = GDMonoMarshal::mono_string_to_godot(p_config);
|
||||
String error_str = GDMono::get_singleton()->update_api_assemblies_from_prebuilt(config);
|
||||
return GDMonoMarshal::mono_string_from_godot(error_str);
|
||||
}
|
||||
|
||||
MonoString *godot_icall_Internal_FullTemplatesDir() {
|
||||
void godot_icall_Internal_FullTemplatesDir(godot_string *r_dest) {
|
||||
String full_templates_dir = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG);
|
||||
return GDMonoMarshal::mono_string_from_godot(full_templates_dir);
|
||||
memnew_placement(r_dest, String(full_templates_dir));
|
||||
}
|
||||
|
||||
MonoString *godot_icall_Internal_SimplifyGodotPath(MonoString *p_path) {
|
||||
String path = GDMonoMarshal::mono_string_to_godot(p_path);
|
||||
return GDMonoMarshal::mono_string_from_godot(path.simplify_path());
|
||||
void godot_icall_Internal_SimplifyGodotPath(const godot_string *p_path, godot_string *r_dest) {
|
||||
String path = *reinterpret_cast<const String *>(p_path);
|
||||
memnew_placement(r_dest, String(path.simplify_path()));
|
||||
}
|
||||
|
||||
MonoBoolean godot_icall_Internal_IsOsxAppBundleInstalled(MonoString *p_bundle_id) {
|
||||
bool godot_icall_Internal_IsOsxAppBundleInstalled(const godot_string *p_bundle_id) {
|
||||
#ifdef OSX_ENABLED
|
||||
String bundle_id = GDMonoMarshal::mono_string_to_godot(p_bundle_id);
|
||||
return (MonoBoolean)osx_is_app_bundle_installed(bundle_id);
|
||||
String bundle_id = *reinterpret_cast<const String *>(p_bundle_id);
|
||||
return (bool)osx_is_app_bundle_installed(bundle_id);
|
||||
#else
|
||||
(void)p_bundle_id; // UNUSED
|
||||
return (MonoBoolean) false;
|
||||
return (bool)false;
|
||||
#endif
|
||||
}
|
||||
|
||||
MonoBoolean godot_icall_Internal_GodotIs32Bits() {
|
||||
bool godot_icall_Internal_GodotIs32Bits() {
|
||||
return sizeof(void *) == 4;
|
||||
}
|
||||
|
||||
MonoBoolean godot_icall_Internal_GodotIsRealTDouble() {
|
||||
bool godot_icall_Internal_GodotIsRealTDouble() {
|
||||
#ifdef REAL_T_IS_DOUBLE
|
||||
return (MonoBoolean) true;
|
||||
return (bool)true;
|
||||
#else
|
||||
return (MonoBoolean) false;
|
||||
return (bool)false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -223,23 +164,15 @@ void godot_icall_Internal_GodotMainIteration() {
|
|||
Main::iteration();
|
||||
}
|
||||
|
||||
uint64_t godot_icall_Internal_GetCoreApiHash() {
|
||||
return ClassDB::get_api_hash(ClassDB::API_CORE);
|
||||
}
|
||||
|
||||
uint64_t godot_icall_Internal_GetEditorApiHash() {
|
||||
return ClassDB::get_api_hash(ClassDB::API_EDITOR);
|
||||
}
|
||||
|
||||
MonoBoolean godot_icall_Internal_IsAssembliesReloadingNeeded() {
|
||||
bool godot_icall_Internal_IsAssembliesReloadingNeeded() {
|
||||
#ifdef GD_MONO_HOT_RELOAD
|
||||
return (MonoBoolean)CSharpLanguage::get_singleton()->is_assembly_reloading_needed();
|
||||
return (bool)CSharpLanguage::get_singleton()->is_assembly_reloading_needed();
|
||||
#else
|
||||
return (MonoBoolean) false;
|
||||
return (bool)false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void godot_icall_Internal_ReloadAssemblies(MonoBoolean p_soft_reload) {
|
||||
void godot_icall_Internal_ReloadAssemblies(bool p_soft_reload) {
|
||||
#ifdef GD_MONO_HOT_RELOAD
|
||||
mono_bind::GodotSharp::get_singleton()->call_deferred(SNAME("_reload_assemblies"), (bool)p_soft_reload);
|
||||
#endif
|
||||
|
@ -249,21 +182,22 @@ void godot_icall_Internal_EditorDebuggerNodeReloadScripts() {
|
|||
EditorDebuggerNode::get_singleton()->reload_scripts();
|
||||
}
|
||||
|
||||
MonoBoolean godot_icall_Internal_ScriptEditorEdit(MonoObject *p_resource, int32_t p_line, int32_t p_col, MonoBoolean p_grab_focus) {
|
||||
Ref<Resource> resource = GDMonoMarshal::mono_object_to_variant(p_resource);
|
||||
return (MonoBoolean)ScriptEditor::get_singleton()->edit(resource, p_line, p_col, (bool)p_grab_focus);
|
||||
bool godot_icall_Internal_ScriptEditorEdit(Resource *p_resource, int32_t p_line, int32_t p_col, bool p_grab_focus) {
|
||||
Ref<Resource> resource = p_resource;
|
||||
return (bool)ScriptEditor::get_singleton()->edit(resource, p_line, p_col, (bool)p_grab_focus);
|
||||
}
|
||||
|
||||
void godot_icall_Internal_EditorNodeShowScriptScreen() {
|
||||
EditorNode::get_singleton()->call("_editor_select", EditorNode::EDITOR_SCRIPT);
|
||||
}
|
||||
|
||||
MonoString *godot_icall_Internal_MonoWindowsInstallRoot() {
|
||||
void godot_icall_Internal_MonoWindowsInstallRoot(godot_string *r_dest) {
|
||||
#ifdef WINDOWS_ENABLED
|
||||
String install_root_dir = GDMono::get_singleton()->get_mono_reg_info().install_root_dir;
|
||||
return GDMonoMarshal::mono_string_from_godot(install_root_dir);
|
||||
memnew_placement(r_dest, String(install_root_dir));
|
||||
#else
|
||||
return nullptr;
|
||||
memnew_placement(r_dest, String);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -282,107 +216,84 @@ void godot_icall_Internal_ScriptEditorDebugger_ReloadScripts() {
|
|||
}
|
||||
}
|
||||
|
||||
MonoArray *godot_icall_Internal_CodeCompletionRequest(int32_t p_kind, MonoString *p_script_file) {
|
||||
String script_file = GDMonoMarshal::mono_string_to_godot(p_script_file);
|
||||
void godot_icall_Internal_CodeCompletionRequest(int32_t p_kind, const godot_string *p_script_file, godot_packed_string_array *r_ret) {
|
||||
String script_file = *reinterpret_cast<const String *>(p_script_file);
|
||||
PackedStringArray suggestions = gdmono::get_code_completion((gdmono::CompletionKind)p_kind, script_file);
|
||||
return GDMonoMarshal::PackedStringArray_to_mono_array(suggestions);
|
||||
memnew_placement(r_ret, PackedStringArray(suggestions));
|
||||
}
|
||||
|
||||
float godot_icall_Globals_EditorScale() {
|
||||
return EDSCALE;
|
||||
}
|
||||
|
||||
MonoObject *godot_icall_Globals_GlobalDef(MonoString *p_setting, MonoObject *p_default_value, MonoBoolean p_restart_if_changed) {
|
||||
String setting = GDMonoMarshal::mono_string_to_godot(p_setting);
|
||||
Variant default_value = GDMonoMarshal::mono_object_to_variant(p_default_value);
|
||||
void godot_icall_Globals_GlobalDef(const godot_string *p_setting, const godot_variant *p_default_value, bool p_restart_if_changed, godot_variant *r_result) {
|
||||
String setting = *reinterpret_cast<const String *>(p_setting);
|
||||
Variant default_value = *reinterpret_cast<const Variant *>(p_default_value);
|
||||
Variant result = _GLOBAL_DEF(setting, default_value, (bool)p_restart_if_changed);
|
||||
return GDMonoMarshal::variant_to_mono_object(result);
|
||||
memnew_placement(r_result, Variant(result));
|
||||
}
|
||||
|
||||
MonoObject *godot_icall_Globals_EditorDef(MonoString *p_setting, MonoObject *p_default_value, MonoBoolean p_restart_if_changed) {
|
||||
String setting = GDMonoMarshal::mono_string_to_godot(p_setting);
|
||||
Variant default_value = GDMonoMarshal::mono_object_to_variant(p_default_value);
|
||||
void godot_icall_Globals_EditorDef(const godot_string *p_setting, const godot_variant *p_default_value, bool p_restart_if_changed, godot_variant *r_result) {
|
||||
String setting = *reinterpret_cast<const String *>(p_setting);
|
||||
Variant default_value = *reinterpret_cast<const Variant *>(p_default_value);
|
||||
Variant result = _EDITOR_DEF(setting, default_value, (bool)p_restart_if_changed);
|
||||
return GDMonoMarshal::variant_to_mono_object(result);
|
||||
memnew_placement(r_result, Variant(result));
|
||||
}
|
||||
|
||||
MonoString *godot_icall_Globals_TTR(MonoString *p_text) {
|
||||
String text = GDMonoMarshal::mono_string_to_godot(p_text);
|
||||
return GDMonoMarshal::mono_string_from_godot(TTR(text));
|
||||
void godot_icall_Globals_TTR(const godot_string *p_text, godot_string *r_dest) {
|
||||
String text = *reinterpret_cast<const String *>(p_text);
|
||||
memnew_placement(r_dest, String(TTR(text)));
|
||||
}
|
||||
|
||||
MonoString *godot_icall_Utils_OS_GetPlatformName() {
|
||||
void godot_icall_Utils_OS_GetPlatformName(godot_string *r_dest) {
|
||||
String os_name = OS::get_singleton()->get_name();
|
||||
return GDMonoMarshal::mono_string_from_godot(os_name);
|
||||
memnew_placement(r_dest, String(os_name));
|
||||
}
|
||||
|
||||
MonoBoolean godot_icall_Utils_OS_UnixFileHasExecutableAccess(MonoString *p_file_path) {
|
||||
bool godot_icall_Utils_OS_UnixFileHasExecutableAccess(const godot_string *p_file_path) {
|
||||
#ifdef UNIX_ENABLED
|
||||
String file_path = GDMonoMarshal::mono_string_to_godot(p_file_path);
|
||||
String file_path = *reinterpret_cast<const String *>(p_file_path);
|
||||
return access(file_path.utf8().get_data(), X_OK) == 0;
|
||||
#else
|
||||
ERR_FAIL_V(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void register_editor_internal_calls() {
|
||||
// GodotSharpDirs
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_ResDataDir", godot_icall_GodotSharpDirs_ResDataDir);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_ResMetadataDir", godot_icall_GodotSharpDirs_ResMetadataDir);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_ResAssembliesBaseDir", godot_icall_GodotSharpDirs_ResAssembliesBaseDir);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_ResAssembliesDir", godot_icall_GodotSharpDirs_ResAssembliesDir);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_ResConfigDir", godot_icall_GodotSharpDirs_ResConfigDir);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_ResTempDir", godot_icall_GodotSharpDirs_ResTempDir);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_ResTempAssembliesBaseDir", godot_icall_GodotSharpDirs_ResTempAssembliesBaseDir);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_ResTempAssembliesDir", godot_icall_GodotSharpDirs_ResTempAssembliesDir);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_MonoUserDir", godot_icall_GodotSharpDirs_MonoUserDir);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_MonoLogsDir", godot_icall_GodotSharpDirs_MonoLogsDir);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_MonoSolutionsDir", godot_icall_GodotSharpDirs_MonoSolutionsDir);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_BuildLogsDirs", godot_icall_GodotSharpDirs_BuildLogsDirs);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_ProjectSlnPath", godot_icall_GodotSharpDirs_ProjectSlnPath);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_ProjectCsProjPath", godot_icall_GodotSharpDirs_ProjectCsProjPath);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_DataEditorToolsDir", godot_icall_GodotSharpDirs_DataEditorToolsDir);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_DataEditorPrebuiltApiDir", godot_icall_GodotSharpDirs_DataEditorPrebuiltApiDir);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_DataMonoEtcDir", godot_icall_GodotSharpDirs_DataMonoEtcDir);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_DataMonoLibDir", godot_icall_GodotSharpDirs_DataMonoLibDir);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.GodotSharpDirs::internal_DataMonoBinDir", godot_icall_GodotSharpDirs_DataMonoBinDir);
|
||||
|
||||
// EditorProgress
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.EditorProgress::internal_Create", godot_icall_EditorProgress_Create);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.EditorProgress::internal_Dispose", godot_icall_EditorProgress_Dispose);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.EditorProgress::internal_Step", godot_icall_EditorProgress_Step);
|
||||
|
||||
// ExportPlugin
|
||||
GDMonoUtils::add_internal_call("GodotTools.Export.ExportPlugin::internal_GetExportedAssemblyDependencies", godot_icall_ExportPlugin_GetExportedAssemblyDependencies);
|
||||
|
||||
// Internals
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_UpdateApiAssembliesFromPrebuilt", godot_icall_Internal_UpdateApiAssembliesFromPrebuilt);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_FullTemplatesDir", godot_icall_Internal_FullTemplatesDir);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_SimplifyGodotPath", godot_icall_Internal_SimplifyGodotPath);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_IsOsxAppBundleInstalled", godot_icall_Internal_IsOsxAppBundleInstalled);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GodotIs32Bits", godot_icall_Internal_GodotIs32Bits);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GodotIsRealTDouble", godot_icall_Internal_GodotIsRealTDouble);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GodotMainIteration", godot_icall_Internal_GodotMainIteration);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GetCoreApiHash", godot_icall_Internal_GetCoreApiHash);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_GetEditorApiHash", godot_icall_Internal_GetEditorApiHash);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_IsAssembliesReloadingNeeded", godot_icall_Internal_IsAssembliesReloadingNeeded);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_ReloadAssemblies", godot_icall_Internal_ReloadAssemblies);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_EditorDebuggerNodeReloadScripts", godot_icall_Internal_EditorDebuggerNodeReloadScripts);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_ScriptEditorEdit", godot_icall_Internal_ScriptEditorEdit);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_EditorNodeShowScriptScreen", godot_icall_Internal_EditorNodeShowScriptScreen);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_MonoWindowsInstallRoot", godot_icall_Internal_MonoWindowsInstallRoot);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_EditorRunPlay", godot_icall_Internal_EditorRunPlay);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_EditorRunStop", godot_icall_Internal_EditorRunStop);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_ScriptEditorDebugger_ReloadScripts", godot_icall_Internal_ScriptEditorDebugger_ReloadScripts);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Internal::internal_CodeCompletionRequest", godot_icall_Internal_CodeCompletionRequest);
|
||||
|
||||
// Globals
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Globals::internal_EditorScale", godot_icall_Globals_EditorScale);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Globals::internal_GlobalDef", godot_icall_Globals_GlobalDef);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Globals::internal_EditorDef", godot_icall_Globals_EditorDef);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Internals.Globals::internal_TTR", godot_icall_Globals_TTR);
|
||||
|
||||
// Utils.OS
|
||||
GDMonoUtils::add_internal_call("GodotTools.Utils.OS::GetPlatformName", godot_icall_Utils_OS_GetPlatformName);
|
||||
GDMonoUtils::add_internal_call("GodotTools.Utils.OS::UnixFileHasExecutableAccess", godot_icall_Utils_OS_UnixFileHasExecutableAccess);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
void *godotsharp_editor_pinvoke_funcs[32] = {
|
||||
(void *)godot_icall_GodotSharpDirs_ResMetadataDir,
|
||||
(void *)godot_icall_GodotSharpDirs_ResTempAssembliesBaseDir,
|
||||
(void *)godot_icall_GodotSharpDirs_MonoUserDir,
|
||||
(void *)godot_icall_GodotSharpDirs_BuildLogsDirs,
|
||||
(void *)godot_icall_GodotSharpDirs_ProjectSlnPath,
|
||||
(void *)godot_icall_GodotSharpDirs_ProjectCsProjPath,
|
||||
(void *)godot_icall_GodotSharpDirs_DataEditorToolsDir,
|
||||
(void *)godot_icall_EditorProgress_Create,
|
||||
(void *)godot_icall_EditorProgress_Dispose,
|
||||
(void *)godot_icall_EditorProgress_Step,
|
||||
(void *)godot_icall_Internal_FullTemplatesDir,
|
||||
(void *)godot_icall_Internal_SimplifyGodotPath,
|
||||
(void *)godot_icall_Internal_IsOsxAppBundleInstalled,
|
||||
(void *)godot_icall_Internal_GodotIs32Bits,
|
||||
(void *)godot_icall_Internal_GodotIsRealTDouble,
|
||||
(void *)godot_icall_Internal_GodotMainIteration,
|
||||
(void *)godot_icall_Internal_IsAssembliesReloadingNeeded,
|
||||
(void *)godot_icall_Internal_ReloadAssemblies,
|
||||
(void *)godot_icall_Internal_EditorDebuggerNodeReloadScripts,
|
||||
(void *)godot_icall_Internal_ScriptEditorEdit,
|
||||
(void *)godot_icall_Internal_EditorNodeShowScriptScreen,
|
||||
(void *)godot_icall_Internal_MonoWindowsInstallRoot,
|
||||
(void *)godot_icall_Internal_EditorRunPlay,
|
||||
(void *)godot_icall_Internal_EditorRunStop,
|
||||
(void *)godot_icall_Internal_ScriptEditorDebugger_ReloadScripts,
|
||||
(void *)godot_icall_Internal_CodeCompletionRequest,
|
||||
(void *)godot_icall_Globals_EditorScale,
|
||||
(void *)godot_icall_Globals_GlobalDef,
|
||||
(void *)godot_icall_Globals_EditorDef,
|
||||
(void *)godot_icall_Globals_TTR,
|
||||
(void *)godot_icall_Utils_OS_GetPlatformName,
|
||||
(void *)godot_icall_Utils_OS_UnixFileHasExecutableAccess,
|
||||
};
|
||||
|
|
|
@ -1,144 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* godotsharp_export.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 "godotsharp_export.h"
|
||||
|
||||
#include <mono/metadata/image.h>
|
||||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/io/file_access_pack.h"
|
||||
#include "core/os/os.h"
|
||||
|
||||
#include "../mono_gd/gd_mono.h"
|
||||
#include "../mono_gd/gd_mono_assembly.h"
|
||||
#include "../mono_gd/gd_mono_cache.h"
|
||||
#include "../utils/macros.h"
|
||||
|
||||
namespace GodotSharpExport {
|
||||
|
||||
MonoAssemblyName *new_mono_assembly_name() {
|
||||
// Mono has no public API to create an empty MonoAssemblyName and the struct is private.
|
||||
// As such the only way to create it is with a stub name and then clear it.
|
||||
|
||||
MonoAssemblyName *aname = mono_assembly_name_new("stub");
|
||||
CRASH_COND(aname == nullptr);
|
||||
mono_assembly_name_free(aname); // Frees the string fields, not the struct
|
||||
return aname;
|
||||
}
|
||||
|
||||
struct AssemblyRefInfo {
|
||||
String name;
|
||||
uint16_t major = 0;
|
||||
uint16_t minor = 0;
|
||||
uint16_t build = 0;
|
||||
uint16_t revision = 0;
|
||||
};
|
||||
|
||||
AssemblyRefInfo get_assemblyref_name(MonoImage *p_image, int index) {
|
||||
const MonoTableInfo *table_info = mono_image_get_table_info(p_image, MONO_TABLE_ASSEMBLYREF);
|
||||
|
||||
uint32_t cols[MONO_ASSEMBLYREF_SIZE];
|
||||
|
||||
mono_metadata_decode_row(table_info, index, cols, MONO_ASSEMBLYREF_SIZE);
|
||||
|
||||
return {
|
||||
String::utf8(mono_metadata_string_heap(p_image, cols[MONO_ASSEMBLYREF_NAME])),
|
||||
(uint16_t)cols[MONO_ASSEMBLYREF_MAJOR_VERSION],
|
||||
(uint16_t)cols[MONO_ASSEMBLYREF_MINOR_VERSION],
|
||||
(uint16_t)cols[MONO_ASSEMBLYREF_BUILD_NUMBER],
|
||||
(uint16_t)cols[MONO_ASSEMBLYREF_REV_NUMBER]
|
||||
};
|
||||
}
|
||||
|
||||
Error get_assembly_dependencies(GDMonoAssembly *p_assembly, MonoAssemblyName *reusable_aname, const Vector<String> &p_search_dirs, Dictionary &r_assembly_dependencies) {
|
||||
MonoImage *image = p_assembly->get_image();
|
||||
|
||||
for (int i = 0; i < mono_image_get_table_rows(image, MONO_TABLE_ASSEMBLYREF); i++) {
|
||||
AssemblyRefInfo ref_info = get_assemblyref_name(image, i);
|
||||
|
||||
const String &ref_name = ref_info.name;
|
||||
|
||||
if (r_assembly_dependencies.has(ref_name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mono_assembly_get_assemblyref(image, i, reusable_aname);
|
||||
|
||||
GDMonoAssembly *ref_assembly = nullptr;
|
||||
if (!GDMono::get_singleton()->load_assembly(ref_name, reusable_aname, &ref_assembly, /* refonly: */ true, p_search_dirs)) {
|
||||
ERR_FAIL_V_MSG(ERR_CANT_RESOLVE, "Cannot load assembly (refonly): '" + ref_name + "'.");
|
||||
}
|
||||
|
||||
r_assembly_dependencies[ref_name] = ref_assembly->get_path();
|
||||
|
||||
Error err = get_assembly_dependencies(ref_assembly, reusable_aname, p_search_dirs, r_assembly_dependencies);
|
||||
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot load one of the dependencies for the assembly: '" + ref_name + "'.");
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
Error get_exported_assembly_dependencies(const Dictionary &p_initial_assemblies,
|
||||
const String &p_build_config, const String &p_custom_bcl_dir, Dictionary &r_assembly_dependencies) {
|
||||
MonoDomain *export_domain = GDMonoUtils::create_domain("GodotEngine.Domain.ProjectExport");
|
||||
ERR_FAIL_NULL_V(export_domain, FAILED);
|
||||
_GDMONO_SCOPE_EXIT_DOMAIN_UNLOAD_(export_domain);
|
||||
|
||||
_GDMONO_SCOPE_DOMAIN_(export_domain);
|
||||
|
||||
Vector<String> search_dirs;
|
||||
GDMonoAssembly::fill_search_dirs(search_dirs, p_build_config, p_custom_bcl_dir);
|
||||
|
||||
if (p_custom_bcl_dir.length()) {
|
||||
// Only one mscorlib can be loaded. We need this workaround to make sure we get it from the right BCL directory.
|
||||
r_assembly_dependencies["mscorlib"] = p_custom_bcl_dir.plus_file("mscorlib.dll").simplify_path();
|
||||
}
|
||||
|
||||
for (const Variant *key = p_initial_assemblies.next(); key; key = p_initial_assemblies.next(key)) {
|
||||
String assembly_name = *key;
|
||||
String assembly_path = p_initial_assemblies[*key];
|
||||
|
||||
GDMonoAssembly *assembly = nullptr;
|
||||
bool load_success = GDMono::get_singleton()->load_assembly_from(assembly_name, assembly_path, &assembly, /* refonly: */ true);
|
||||
|
||||
ERR_FAIL_COND_V_MSG(!load_success, ERR_CANT_RESOLVE, "Cannot load assembly (refonly): '" + assembly_name + "'.");
|
||||
|
||||
MonoAssemblyName *reusable_aname = new_mono_assembly_name();
|
||||
SCOPE_EXIT { mono_free(reusable_aname); };
|
||||
|
||||
Error err = get_assembly_dependencies(assembly, reusable_aname, search_dirs, r_assembly_dependencies);
|
||||
if (err != OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
} // namespace GodotSharpExport
|
|
@ -1,48 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* godotsharp_export.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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef GODOTSHARP_EXPORT_H
|
||||
#define GODOTSHARP_EXPORT_H
|
||||
|
||||
#include "core/error/error_list.h"
|
||||
#include "core/string/ustring.h"
|
||||
#include "core/variant/dictionary.h"
|
||||
|
||||
#include "../mono_gd/gd_mono_header.h"
|
||||
|
||||
namespace GodotSharpExport {
|
||||
|
||||
Error get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String> &p_search_dirs, Dictionary &r_dependencies);
|
||||
|
||||
Error get_exported_assembly_dependencies(const Dictionary &p_initial_assemblies,
|
||||
const String &p_build_config, const String &p_custom_lib_dir, Dictionary &r_assembly_dependencies);
|
||||
} // namespace GodotSharpExport
|
||||
|
||||
#endif // GODOTSHARP_EXPORT_H
|
|
@ -0,0 +1,17 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<LangVersion>9</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
|
||||
<!-- To generate the .runtimeconfig.json file-->
|
||||
<EnableDynamicLoading>true</EnableDynamicLoading>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\GodotSharp\GodotSharp.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
195
modules/mono/glue/GodotSharp/GodotPlugins/Main.cs
Normal file
195
modules/mono/glue/GodotSharp/GodotPlugins/Main.cs
Normal file
|
@ -0,0 +1,195 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Loader;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
namespace GodotPlugins
|
||||
{
|
||||
public static class Main
|
||||
{
|
||||
private static readonly List<AssemblyName> SharedAssemblies = new();
|
||||
private static readonly Assembly CoreApiAssembly = typeof(Godot.Object).Assembly;
|
||||
private static Assembly? _editorApiAssembly;
|
||||
|
||||
private static readonly AssemblyLoadContext MainLoadContext =
|
||||
AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly()) ??
|
||||
AssemblyLoadContext.Default;
|
||||
|
||||
// Right now we do it this way for simplicity as hot-reload is disabled. It will need to be changed later.
|
||||
[UnmanagedCallersOnly]
|
||||
internal static unsafe godot_bool Initialize(godot_bool editorHint,
|
||||
PluginsCallbacks* pluginsCallbacks, Godot.Bridge.ManagedCallbacks* managedCallbacks)
|
||||
{
|
||||
try
|
||||
{
|
||||
SharedAssemblies.Add(CoreApiAssembly.GetName());
|
||||
|
||||
if (editorHint.ToBool())
|
||||
{
|
||||
_editorApiAssembly = Assembly.Load("GodotSharpEditor");
|
||||
SharedAssemblies.Add(_editorApiAssembly.GetName());
|
||||
}
|
||||
|
||||
NativeLibrary.SetDllImportResolver(CoreApiAssembly, OnResolveDllImport);
|
||||
|
||||
*pluginsCallbacks = new()
|
||||
{
|
||||
LoadProjectAssemblyCallback = &LoadProjectAssembly,
|
||||
LoadToolsAssemblyCallback = &LoadToolsAssembly,
|
||||
};
|
||||
|
||||
*managedCallbacks = Godot.Bridge.ManagedCallbacks.Create();
|
||||
|
||||
return godot_bool.True;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.Error.WriteLine(e);
|
||||
*pluginsCallbacks = default;
|
||||
*managedCallbacks = default;
|
||||
return false.ToGodotBool();
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct PluginsCallbacks
|
||||
{
|
||||
public unsafe delegate* unmanaged<char*, godot_bool> LoadProjectAssemblyCallback;
|
||||
public unsafe delegate* unmanaged<char*, IntPtr> LoadToolsAssemblyCallback;
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static unsafe godot_bool LoadProjectAssembly(char* nAssemblyPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
string assemblyPath = new(nAssemblyPath);
|
||||
|
||||
var assembly = LoadPlugin(assemblyPath);
|
||||
|
||||
var method = CoreApiAssembly.GetType("Godot.Bridge.ScriptManagerBridge")?
|
||||
.GetMethod("LookupScriptsInAssembly",
|
||||
BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
|
||||
if (method == null)
|
||||
{
|
||||
throw new MissingMethodException("Godot.Bridge.ScriptManagerBridge",
|
||||
"LookupScriptsInAssembly");
|
||||
}
|
||||
|
||||
method.Invoke(null, new object[] { assembly });
|
||||
|
||||
return godot_bool.True;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.Error.WriteLine(e);
|
||||
return false.ToGodotBool();
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static unsafe IntPtr LoadToolsAssembly(char* nAssemblyPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
string assemblyPath = new(nAssemblyPath);
|
||||
|
||||
if (_editorApiAssembly == null)
|
||||
throw new InvalidOperationException("The Godot editor API assembly is not loaded");
|
||||
|
||||
var assembly = LoadPlugin(assemblyPath);
|
||||
|
||||
NativeLibrary.SetDllImportResolver(assembly, OnResolveDllImport);
|
||||
|
||||
var method = assembly.GetType("GodotTools.GodotSharpEditor")?
|
||||
.GetMethod("InternalCreateInstance",
|
||||
BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
|
||||
if (method == null)
|
||||
{
|
||||
throw new MissingMethodException("GodotTools.GodotSharpEditor",
|
||||
"InternalCreateInstance");
|
||||
}
|
||||
|
||||
return (IntPtr?)method.Invoke(null, null) ?? IntPtr.Zero;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.Error.WriteLine(e);
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
private static Assembly LoadPlugin(string assemblyPath)
|
||||
{
|
||||
string assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);
|
||||
|
||||
var sharedAssemblies = new List<string>();
|
||||
|
||||
foreach (var sharedAssembly in SharedAssemblies)
|
||||
{
|
||||
string? sharedAssemblyName = sharedAssembly.Name;
|
||||
if (sharedAssemblyName != null)
|
||||
sharedAssemblies.Add(sharedAssemblyName);
|
||||
}
|
||||
|
||||
var loadContext = new PluginLoadContext(assemblyPath, sharedAssemblies, MainLoadContext);
|
||||
return loadContext.LoadFromAssemblyName(new AssemblyName(assemblyName));
|
||||
}
|
||||
|
||||
public static IntPtr OnResolveDllImport(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
|
||||
{
|
||||
if (libraryName == "__Internal")
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
return Win32.GetModuleHandle(null);
|
||||
}
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
return Linux.dlopen(null, Linux.RTLD_LAZY);
|
||||
}
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
{
|
||||
return MacOS.dlopen(null, MacOS.RTLD_LAZY);
|
||||
}
|
||||
}
|
||||
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
private static class MacOS
|
||||
{
|
||||
private const string SystemLibrary = "/usr/lib/libSystem.dylib";
|
||||
|
||||
public const int RTLD_LAZY = 1;
|
||||
|
||||
[DllImport(SystemLibrary)]
|
||||
public static extern IntPtr dlopen(string? path, int mode);
|
||||
}
|
||||
|
||||
private static class Linux
|
||||
{
|
||||
private const string SystemLibrary = "dl";
|
||||
|
||||
public const int RTLD_LAZY = 1;
|
||||
|
||||
[DllImport(SystemLibrary)]
|
||||
public static extern IntPtr dlopen(string? path, int mode);
|
||||
}
|
||||
|
||||
private static class Win32
|
||||
{
|
||||
private const string SystemLibrary = "Kernel32.dll";
|
||||
|
||||
[DllImport(SystemLibrary)]
|
||||
public static extern IntPtr GetModuleHandle(string? lpModuleName);
|
||||
}
|
||||
// ReSharper restore InconsistentNaming
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Loader;
|
||||
|
||||
namespace GodotPlugins
|
||||
{
|
||||
public class PluginLoadContext : AssemblyLoadContext
|
||||
{
|
||||
private readonly AssemblyDependencyResolver _resolver;
|
||||
private readonly ICollection<string> _sharedAssemblies;
|
||||
private readonly AssemblyLoadContext _mainLoadContext;
|
||||
|
||||
public PluginLoadContext(string pluginPath, ICollection<string> sharedAssemblies,
|
||||
AssemblyLoadContext mainLoadContext)
|
||||
{
|
||||
Console.WriteLine(pluginPath);
|
||||
Console.Out.Flush();
|
||||
_resolver = new AssemblyDependencyResolver(pluginPath);
|
||||
_sharedAssemblies = sharedAssemblies;
|
||||
_mainLoadContext = mainLoadContext;
|
||||
}
|
||||
|
||||
protected override Assembly? Load(AssemblyName assemblyName)
|
||||
{
|
||||
if (assemblyName.Name == null)
|
||||
return null;
|
||||
|
||||
if (_sharedAssemblies.Contains(assemblyName.Name))
|
||||
return _mainLoadContext.LoadFromAssemblyName(assemblyName);
|
||||
|
||||
string? assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
|
||||
if (assemblyPath != null)
|
||||
{
|
||||
// Load in memory to prevent locking the file
|
||||
using var assemblyFile = File.Open(assemblyPath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
string pdbPath = Path.ChangeExtension(assemblyPath, ".pdb");
|
||||
|
||||
if (File.Exists(pdbPath))
|
||||
{
|
||||
using var pdbFile = File.Open(pdbPath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
return LoadFromStream(assemblyFile, pdbFile);
|
||||
}
|
||||
|
||||
return LoadFromStream(assemblyFile);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
|
||||
{
|
||||
string? libraryPath = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName);
|
||||
if (libraryPath != null)
|
||||
return LoadUnmanagedDllFromPath(libraryPath);
|
||||
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,6 +4,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotSharp", "GodotSharp\Go
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotSharpEditor", "GodotSharpEditor\GodotSharpEditor.csproj", "{8FBEC238-D944-4074-8548-B3B524305905}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotPlugins", "GodotPlugins\GodotPlugins.csproj", "{944B77DB-497B-47F5-A1E3-81C35E3E9D4E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
@ -18,5 +20,9 @@ Global
|
|||
{8FBEC238-D944-4074-8548-B3B524305905}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8FBEC238-D944-4074-8548-B3B524305905}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8FBEC238-D944-4074-8548-B3B524305905}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{944B77DB-497B-47F5-A1E3-81C35E3E9D4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{944B77DB-497B-47F5-A1E3-81C35E3E9D4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{944B77DB-497B-47F5-A1E3-81C35E3E9D4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{944B77DB-497B-47F5-A1E3-81C35E3E9D4E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
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,27 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
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;
|
||||
public godot_array NativeValue;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new empty <see cref="Array"/>.
|
||||
/// </summary>
|
||||
public Array()
|
||||
{
|
||||
safeHandle = new ArraySafeHandle(godot_icall_Array_Ctor());
|
||||
NativeValue = NativeFuncs.godotsharp_array_new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -58,6 +38,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>
|
||||
|
@ -66,28 +47,44 @@ namespace Godot.Collections
|
|||
public Array(params object[] array) : this()
|
||||
{
|
||||
if (array == null)
|
||||
{
|
||||
throw new NullReferenceException($"Parameter '{nameof(array)} cannot be null.'");
|
||||
}
|
||||
safeHandle = new ArraySafeHandle(godot_icall_Array_Ctor_MonoArray(array));
|
||||
|
||||
NativeValue = NativeFuncs.godotsharp_array_new();
|
||||
int length = array.Length;
|
||||
|
||||
Resize(length);
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
this[i] = array[i];
|
||||
}
|
||||
|
||||
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 +94,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;
|
||||
NativeFuncs.godotsharp_array_duplicate(ref NativeValue, deep.ToGodotBool(), out newArray);
|
||||
return CreateTakingOwnershipOfDisposableValue(newArray);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -105,18 +104,12 @@ namespace Godot.Collections
|
|||
/// </summary>
|
||||
/// <param name="newSize">The new size of the array.</param>
|
||||
/// <returns><see cref="Error.Ok"/> if successful, or an error code.</returns>
|
||||
public Error Resize(int newSize)
|
||||
{
|
||||
return godot_icall_Array_Resize(GetPtr(), newSize);
|
||||
}
|
||||
public Error Resize(int newSize) => NativeFuncs.godotsharp_array_resize(ref NativeValue, newSize);
|
||||
|
||||
/// <summary>
|
||||
/// Shuffles the contents of this <see cref="Array"/> into a random order.
|
||||
/// </summary>
|
||||
public void Shuffle()
|
||||
{
|
||||
godot_icall_Array_Shuffle(GetPtr());
|
||||
}
|
||||
public void Shuffle() => NativeFuncs.godotsharp_array_shuffle(ref NativeValue);
|
||||
|
||||
/// <summary>
|
||||
/// Concatenates these two <see cref="Array"/>s.
|
||||
|
@ -126,26 +119,16 @@ 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()));
|
||||
}
|
||||
int leftCount = left.Count;
|
||||
int rightCount = right.Count;
|
||||
|
||||
// IDisposable
|
||||
Array newArray = left.Duplicate(deep: false);
|
||||
newArray.Resize(leftCount + rightCount);
|
||||
|
||||
/// <summary>
|
||||
/// Disposes of this <see cref="Array"/>.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (disposed)
|
||||
return;
|
||||
for (int i = 0; i < rightCount; i++)
|
||||
newArray[i + leftCount] = right[i];
|
||||
|
||||
if (safeHandle != null)
|
||||
{
|
||||
safeHandle.Dispose();
|
||||
safeHandle = null;
|
||||
}
|
||||
|
||||
disposed = true;
|
||||
return newArray;
|
||||
}
|
||||
|
||||
// IList
|
||||
|
@ -158,10 +141,20 @@ namespace Godot.Collections
|
|||
/// Returns the object at the given index.
|
||||
/// </summary>
|
||||
/// <value>The object at the given index.</value>
|
||||
public object this[int index]
|
||||
public unsafe object this[int index]
|
||||
{
|
||||
get => godot_icall_Array_At(GetPtr(), index);
|
||||
set => godot_icall_Array_SetAt(GetPtr(), index, value);
|
||||
get
|
||||
{
|
||||
GetVariantBorrowElementAt(index, out godot_variant borrowElem);
|
||||
return Marshaling.variant_to_mono_object(&borrowElem);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (index < 0 || index >= Count)
|
||||
throw new IndexOutOfRangeException();
|
||||
godot_variant* ptrw = NativeFuncs.godotsharp_array_ptrw(ref NativeValue);
|
||||
ptrw[index] = Marshaling.mono_object_to_variant(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -170,19 +163,23 @@ 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 unsafe int Add(object value)
|
||||
{
|
||||
using godot_variant variantValue = Marshaling.mono_object_to_variant(value);
|
||||
return NativeFuncs.godotsharp_array_add(ref NativeValue, &variantValue);
|
||||
}
|
||||
|
||||
/// <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) => IndexOf(value) != -1;
|
||||
|
||||
/// <summary>
|
||||
/// Erases all items from this <see cref="Array"/>.
|
||||
/// </summary>
|
||||
public void Clear() => godot_icall_Array_Clear(GetPtr());
|
||||
public void Clear() => Resize(0);
|
||||
|
||||
/// <summary>
|
||||
/// Searches this <see cref="Array"/> for an object
|
||||
|
@ -190,7 +187,11 @@ 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 unsafe int IndexOf(object value)
|
||||
{
|
||||
using godot_variant variantValue = Marshaling.mono_object_to_variant(value);
|
||||
return NativeFuncs.godotsharp_array_index_of(ref NativeValue, &variantValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts a new object at a given position in the array.
|
||||
|
@ -200,20 +201,38 @@ 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 unsafe void Insert(int index, object value)
|
||||
{
|
||||
if (index < 0 || index > Count)
|
||||
throw new IndexOutOfRangeException();
|
||||
|
||||
using godot_variant variantValue = Marshaling.mono_object_to_variant(value);
|
||||
NativeFuncs.godotsharp_array_insert(ref NativeValue, index, &variantValue);
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
int index = IndexOf(value);
|
||||
if (index >= 0)
|
||||
RemoveAt(index);
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
if (index < 0 || index > Count)
|
||||
throw new IndexOutOfRangeException();
|
||||
|
||||
NativeFuncs.godotsharp_array_remove_at(ref NativeValue, index);
|
||||
}
|
||||
|
||||
// ICollection
|
||||
|
||||
|
@ -222,7 +241,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 => NativeValue.Size;
|
||||
|
||||
object ICollection.SyncRoot => this;
|
||||
|
||||
|
@ -233,17 +252,35 @@ namespace Godot.Collections
|
|||
/// untyped C# array, starting at the given index.
|
||||
/// </summary>
|
||||
/// <param name="array">The array to copy to.</param>
|
||||
/// <param name="index">The index to start at.</param>
|
||||
public void CopyTo(System.Array array, int index)
|
||||
/// <param name="destIndex">The index to start at.</param>
|
||||
public void CopyTo(System.Array array, int destIndex)
|
||||
{
|
||||
if (array == null)
|
||||
throw new ArgumentNullException(nameof(array), "Value cannot be null.");
|
||||
|
||||
if (index < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(index), "Number was less than the array's lower bound in the first dimension.");
|
||||
if (destIndex < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(destIndex),
|
||||
"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);
|
||||
int count = Count;
|
||||
|
||||
if (array.Length < (destIndex + count))
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
|
||||
}
|
||||
|
||||
unsafe
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
object obj = Marshaling.variant_to_mono_object(&(*NativeValue._p)._arrayVector._ptr[i]);
|
||||
array.SetValue(obj, destIndex);
|
||||
destIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IEnumerable
|
||||
|
@ -266,75 +303,39 @@ namespace Godot.Collections
|
|||
/// Converts this <see cref="Array"/> to a string.
|
||||
/// </summary>
|
||||
/// <returns>A string representation of this array.</returns>
|
||||
public override string ToString()
|
||||
public override unsafe string ToString()
|
||||
{
|
||||
return godot_icall_Array_ToString(GetPtr());
|
||||
using godot_string str = default;
|
||||
NativeFuncs.godotsharp_array_to_string(ref NativeValue, &str);
|
||||
return Marshaling.mono_string_from_godot(str);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static IntPtr godot_icall_Array_Ctor();
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static IntPtr godot_icall_Array_Ctor_MonoArray(System.Array array);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Array_Dtor(IntPtr ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static object godot_icall_Array_At(IntPtr ptr, int index);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static object godot_icall_Array_At_Generic(IntPtr ptr, int index, int elemTypeEncoding, IntPtr elemTypeClass);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Array_SetAt(IntPtr ptr, int index, object value);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static int godot_icall_Array_Count(IntPtr ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static int godot_icall_Array_Add(IntPtr ptr, object item);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Array_Clear(IntPtr ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static IntPtr godot_icall_Array_Concatenate(IntPtr left, IntPtr right);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static bool godot_icall_Array_Contains(IntPtr ptr, object item);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Array_CopyTo(IntPtr ptr, System.Array array, int arrayIndex);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static IntPtr godot_icall_Array_Duplicate(IntPtr ptr, bool deep);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static int godot_icall_Array_IndexOf(IntPtr ptr, object item);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Array_Insert(IntPtr ptr, int index, object item);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static bool godot_icall_Array_Remove(IntPtr ptr, object item);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Array_RemoveAt(IntPtr ptr, int index);
|
||||
|
||||
[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);
|
||||
/// <summary>
|
||||
/// The variant returned via the <paramref name="elem"/> parameter is owned by the Array and must not be disposed.
|
||||
/// </summary>
|
||||
internal void GetVariantBorrowElementAt(int index, out godot_variant elem)
|
||||
{
|
||||
if (index < 0 || index >= Count)
|
||||
throw new IndexOutOfRangeException();
|
||||
GetVariantBorrowElementAtUnchecked(index, out elem);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The variant returned via the <paramref name="elem"/> parameter is owned by the Array and must not be disposed.
|
||||
/// </summary>
|
||||
internal unsafe void GetVariantBorrowElementAtUnchecked(int index, out godot_variant elem)
|
||||
{
|
||||
elem = (*NativeValue._p)._arrayVector._ptr[index];
|
||||
}
|
||||
}
|
||||
|
||||
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 +343,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 +376,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 +390,8 @@ namespace Godot.Collections
|
|||
{
|
||||
throw new NullReferenceException($"Parameter '{nameof(array)} cannot be null.'");
|
||||
}
|
||||
objectArray = new Array(array);
|
||||
|
||||
_underlyingArray = new Array(array);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -395,23 +400,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 +413,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 +423,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 +433,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 +441,7 @@ namespace Godot.Collections
|
|||
/// </summary>
|
||||
public void Shuffle()
|
||||
{
|
||||
objectArray.Shuffle();
|
||||
_underlyingArray.Shuffle();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -458,7 +452,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 +463,15 @@ 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
|
||||
{
|
||||
_underlyingArray.GetVariantBorrowElementAt(index, out godot_variant borrowElem);
|
||||
unsafe
|
||||
{
|
||||
return (T)Marshaling.variant_to_mono_object_of_type(&borrowElem, TypeOfElements);
|
||||
}
|
||||
}
|
||||
set => _underlyingArray[index] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -481,7 +482,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 +495,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 +504,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 +514,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 +526,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 +534,7 @@ namespace Godot.Collections
|
|||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
objectArray.Clear();
|
||||
_underlyingArray.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -546,7 +544,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>
|
||||
|
@ -561,19 +559,18 @@ namespace Godot.Collections
|
|||
throw new ArgumentNullException(nameof(array), "Value cannot be null.");
|
||||
|
||||
if (arrayIndex < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(arrayIndex), "Number was less than the array's lower bound in the first dimension.");
|
||||
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.");
|
||||
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 +583,14 @@ namespace Godot.Collections
|
|||
/// <returns>A bool indicating success or failure.</returns>
|
||||
public bool Remove(T item)
|
||||
{
|
||||
return Array.godot_icall_Array_Remove(GetPtr(), item);
|
||||
int index = IndexOf(item);
|
||||
if (index >= 0)
|
||||
{
|
||||
RemoveAt(index);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// IEnumerable<T>
|
||||
|
@ -597,23 +601,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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +1,27 @@
|
|||
using System;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace Godot
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Assembly)]
|
||||
public class AssemblyHasScriptsAttribute : Attribute
|
||||
{
|
||||
private readonly bool requiresLookup;
|
||||
private readonly System.Type[] scriptTypes;
|
||||
public bool RequiresLookup { get; private set; }
|
||||
public Type[]? ScriptTypes { get; private set; }
|
||||
|
||||
public AssemblyHasScriptsAttribute()
|
||||
{
|
||||
requiresLookup = true;
|
||||
RequiresLookup = true;
|
||||
ScriptTypes = null;
|
||||
}
|
||||
|
||||
public AssemblyHasScriptsAttribute(System.Type[] scriptTypes)
|
||||
public AssemblyHasScriptsAttribute(Type[] scriptTypes)
|
||||
{
|
||||
requiresLookup = false;
|
||||
this.scriptTypes = scriptTypes;
|
||||
RequiresLookup = false;
|
||||
ScriptTypes = scriptTypes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#nullable restore
|
||||
|
|
|
@ -5,11 +5,11 @@ namespace Godot
|
|||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
|
||||
public class ScriptPathAttribute : Attribute
|
||||
{
|
||||
private string path;
|
||||
public string Path { get; private set; }
|
||||
|
||||
public ScriptPathAttribute(string path)
|
||||
{
|
||||
this.path = path;
|
||||
Path = path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
namespace Godot.Bridge
|
||||
{
|
||||
internal static class CSharpInstanceBridge
|
||||
{
|
||||
[UnmanagedCallersOnly]
|
||||
internal static unsafe godot_bool Call(IntPtr godotObjectGCHandle, godot_string_name* method,
|
||||
godot_variant** args, int argCount, godot_variant_call_error* refCallError, godot_variant* ret)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Performance is not critical here as this will be replaced with source generators.
|
||||
var godotObject = (Object)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
|
||||
|
||||
if (godotObject == null)
|
||||
{
|
||||
*ret = default;
|
||||
(*refCallError).error = godot_variant_call_error_error.GODOT_CALL_ERROR_CALL_ERROR_INSTANCE_IS_NULL;
|
||||
return false.ToGodotBool();
|
||||
}
|
||||
|
||||
using godot_string dest = default;
|
||||
NativeFuncs.godotsharp_string_name_as_string(&dest, method);
|
||||
string methodStr = Marshaling.mono_string_from_godot(dest);
|
||||
|
||||
_ = godotObject.InternalGodotScriptCall(methodStr, args, argCount, out godot_variant retValue);
|
||||
*ret = retValue;
|
||||
return true.ToGodotBool();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||
*ret = default;
|
||||
return false.ToGodotBool();
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static unsafe godot_bool Set(IntPtr godotObjectGCHandle, godot_string_name* name, godot_variant* value)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Performance is not critical here as this will be replaced with source generators.
|
||||
var godotObject = (Object)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
|
||||
|
||||
if (godotObject == null)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
var nameManaged = StringName.CreateTakingOwnershipOfDisposableValue(
|
||||
NativeFuncs.godotsharp_string_name_new_copy(name));
|
||||
|
||||
if (godotObject.InternalGodotScriptSetFieldOrPropViaReflection(nameManaged.ToString(), value))
|
||||
return true.ToGodotBool();
|
||||
|
||||
object valueManaged = Marshaling.variant_to_mono_object(value);
|
||||
|
||||
return godotObject._Set(nameManaged, valueManaged).ToGodotBool();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||
return false.ToGodotBool();
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static unsafe godot_bool Get(IntPtr godotObjectGCHandle, godot_string_name* name,
|
||||
godot_variant* outRet)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Performance is not critical here as this will be replaced with source generators.
|
||||
var godotObject = (Object)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
|
||||
|
||||
if (godotObject == null)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
var nameManaged = StringName.CreateTakingOwnershipOfDisposableValue(
|
||||
NativeFuncs.godotsharp_string_name_new_copy(name));
|
||||
|
||||
if (godotObject.InternalGodotScriptGetFieldOrPropViaReflection(nameManaged.ToString(),
|
||||
out godot_variant outRetValue))
|
||||
{
|
||||
*outRet = outRetValue;
|
||||
return true.ToGodotBool();
|
||||
}
|
||||
|
||||
object ret = godotObject._Get(nameManaged);
|
||||
|
||||
if (ret == null)
|
||||
{
|
||||
*outRet = default;
|
||||
return false.ToGodotBool();
|
||||
}
|
||||
|
||||
*outRet = Marshaling.mono_object_to_variant(ret);
|
||||
return true.ToGodotBool();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||
*outRet = default;
|
||||
return false.ToGodotBool();
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static void CallDispose(IntPtr godotObjectGCHandle, godot_bool okIfNull)
|
||||
{
|
||||
try
|
||||
{
|
||||
var godotObject = (Object)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
|
||||
|
||||
if (okIfNull.ToBool())
|
||||
godotObject?.Dispose();
|
||||
else
|
||||
godotObject!.Dispose();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static unsafe void CallToString(IntPtr godotObjectGCHandle, godot_string* outRes, godot_bool* outValid)
|
||||
{
|
||||
try
|
||||
{
|
||||
var self = (Object)GCHandle.FromIntPtr(godotObjectGCHandle).Target;
|
||||
|
||||
if (self == null)
|
||||
{
|
||||
*outRes = default;
|
||||
*outValid = false.ToGodotBool();
|
||||
return;
|
||||
}
|
||||
|
||||
var resultStr = self.ToString();
|
||||
|
||||
if (resultStr == null)
|
||||
{
|
||||
*outRes = default;
|
||||
*outValid = false.ToGodotBool();
|
||||
return;
|
||||
}
|
||||
|
||||
*outRes = Marshaling.mono_string_to_godot(resultStr);
|
||||
*outValid = true.ToGodotBool();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||
*outRes = default;
|
||||
*outValid = false.ToGodotBool();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
namespace Godot.Bridge
|
||||
{
|
||||
internal static class GCHandleBridge
|
||||
{
|
||||
[UnmanagedCallersOnly]
|
||||
internal static void FreeGCHandle(IntPtr gcHandlePtr)
|
||||
{
|
||||
try
|
||||
{
|
||||
GCHandle.FromIntPtr(gcHandlePtr).Free();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
namespace Godot.Bridge
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe struct ManagedCallbacks
|
||||
{
|
||||
// @formatter:off
|
||||
public delegate* unmanaged<IntPtr, godot_variant**, int, godot_bool*, void> SignalAwaiter_SignalCallback;
|
||||
public delegate* unmanaged<IntPtr, godot_variant**, uint, godot_variant*, void> DelegateUtils_InvokeWithVariantArgs;
|
||||
public delegate* unmanaged<IntPtr, IntPtr, godot_bool> DelegateUtils_DelegateEquals;
|
||||
public delegate* unmanaged<void> ScriptManagerBridge_FrameCallback;
|
||||
public delegate* unmanaged<godot_string_name*, IntPtr, IntPtr> ScriptManagerBridge_CreateManagedForGodotObjectBinding;
|
||||
public delegate* unmanaged<IntPtr, IntPtr, godot_variant**, int, godot_bool> ScriptManagerBridge_CreateManagedForGodotObjectScriptInstance;
|
||||
public delegate* unmanaged<IntPtr, godot_string_name*, void> ScriptManagerBridge_GetScriptNativeName;
|
||||
public delegate* unmanaged<IntPtr, IntPtr, void> ScriptManagerBridge_SetGodotObjectPtr;
|
||||
public delegate* unmanaged<IntPtr, godot_string_name*, godot_variant**, int, godot_bool*, void> ScriptManagerBridge_RaiseEventSignal;
|
||||
public delegate* unmanaged<IntPtr, godot_dictionary*, void> ScriptManagerBridge_GetScriptSignalList;
|
||||
public delegate* unmanaged<IntPtr, godot_string*, godot_bool> ScriptManagerBridge_HasScriptSignal;
|
||||
public delegate* unmanaged<IntPtr, godot_string*, godot_bool, godot_bool> ScriptManagerBridge_HasMethodUnknownParams;
|
||||
public delegate* unmanaged<IntPtr, IntPtr, godot_bool> ScriptManagerBridge_ScriptIsOrInherits;
|
||||
public delegate* unmanaged<IntPtr, godot_string*, godot_bool> ScriptManagerBridge_AddScriptBridge;
|
||||
public delegate* unmanaged<IntPtr, void> ScriptManagerBridge_RemoveScriptBridge;
|
||||
public delegate* unmanaged<IntPtr, godot_bool*, godot_dictionary*, void> ScriptManagerBridge_UpdateScriptClassInfo;
|
||||
public delegate* unmanaged<IntPtr, IntPtr*, godot_bool, godot_bool> ScriptManagerBridge_SwapGCHandleForType;
|
||||
public delegate* unmanaged<IntPtr, godot_string_name*, godot_variant**, int, godot_variant_call_error*, godot_variant*, godot_bool> CSharpInstanceBridge_Call;
|
||||
public delegate* unmanaged<IntPtr, godot_string_name*, godot_variant*, godot_bool> CSharpInstanceBridge_Set;
|
||||
public delegate* unmanaged<IntPtr, godot_string_name*, godot_variant*, godot_bool> CSharpInstanceBridge_Get;
|
||||
public delegate* unmanaged<IntPtr, godot_bool, void> CSharpInstanceBridge_CallDispose;
|
||||
public delegate* unmanaged<IntPtr, godot_string*, godot_bool*, void> CSharpInstanceBridge_CallToString;
|
||||
public delegate* unmanaged<IntPtr, void> GCHandleBridge_FreeGCHandle;
|
||||
public delegate* unmanaged<void> DebuggingUtils_InstallTraceListener;
|
||||
public delegate* unmanaged<void> Dispatcher_InitializeDefaultGodotTaskScheduler;
|
||||
// @formatter:on
|
||||
|
||||
public static ManagedCallbacks Create()
|
||||
{
|
||||
return new()
|
||||
{
|
||||
// @formatter:off
|
||||
SignalAwaiter_SignalCallback = &SignalAwaiter.SignalCallback,
|
||||
DelegateUtils_InvokeWithVariantArgs = &DelegateUtils.InvokeWithVariantArgs,
|
||||
DelegateUtils_DelegateEquals = &DelegateUtils.DelegateEquals,
|
||||
ScriptManagerBridge_FrameCallback = &ScriptManagerBridge.FrameCallback,
|
||||
ScriptManagerBridge_CreateManagedForGodotObjectBinding = &ScriptManagerBridge.CreateManagedForGodotObjectBinding,
|
||||
ScriptManagerBridge_CreateManagedForGodotObjectScriptInstance = &ScriptManagerBridge.CreateManagedForGodotObjectScriptInstance,
|
||||
ScriptManagerBridge_GetScriptNativeName = &ScriptManagerBridge.GetScriptNativeName,
|
||||
ScriptManagerBridge_SetGodotObjectPtr = &ScriptManagerBridge.SetGodotObjectPtr,
|
||||
ScriptManagerBridge_RaiseEventSignal = &ScriptManagerBridge.RaiseEventSignal,
|
||||
ScriptManagerBridge_GetScriptSignalList = &ScriptManagerBridge.GetScriptSignalList,
|
||||
ScriptManagerBridge_HasScriptSignal = &ScriptManagerBridge.HasScriptSignal,
|
||||
ScriptManagerBridge_HasMethodUnknownParams = &ScriptManagerBridge.HasMethodUnknownParams,
|
||||
ScriptManagerBridge_ScriptIsOrInherits = &ScriptManagerBridge.ScriptIsOrInherits,
|
||||
ScriptManagerBridge_AddScriptBridge = &ScriptManagerBridge.AddScriptBridge,
|
||||
ScriptManagerBridge_RemoveScriptBridge = &ScriptManagerBridge.RemoveScriptBridge,
|
||||
ScriptManagerBridge_UpdateScriptClassInfo = &ScriptManagerBridge.UpdateScriptClassInfo,
|
||||
ScriptManagerBridge_SwapGCHandleForType = &ScriptManagerBridge.SwapGCHandleForType,
|
||||
CSharpInstanceBridge_Call = &CSharpInstanceBridge.Call,
|
||||
CSharpInstanceBridge_Set = &CSharpInstanceBridge.Set,
|
||||
CSharpInstanceBridge_Get = &CSharpInstanceBridge.Get,
|
||||
CSharpInstanceBridge_CallDispose = &CSharpInstanceBridge.CallDispose,
|
||||
CSharpInstanceBridge_CallToString = &CSharpInstanceBridge.CallToString,
|
||||
GCHandleBridge_FreeGCHandle = &GCHandleBridge.FreeGCHandle,
|
||||
DebuggingUtils_InstallTraceListener = &DebuggingUtils.InstallTraceListener,
|
||||
Dispatcher_InitializeDefaultGodotTaskScheduler = &Dispatcher.InitializeDefaultGodotTaskScheduler,
|
||||
// @formatter:on
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,668 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Serialization;
|
||||
using Godot.Collections;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
namespace Godot.Bridge
|
||||
{
|
||||
internal static class ScriptManagerBridge
|
||||
{
|
||||
private static System.Collections.Generic.Dictionary<string, ScriptLookupInfo> _scriptLookupMap = new();
|
||||
private static System.Collections.Generic.Dictionary<IntPtr, Type> _scriptBridgeMap = new();
|
||||
|
||||
private struct ScriptLookupInfo
|
||||
{
|
||||
public string ClassNamespace { get; private set; }
|
||||
public string ClassName { get; private set; }
|
||||
public Type ScriptType { get; private set; }
|
||||
|
||||
public ScriptLookupInfo(string classNamespace, string className, Type scriptType)
|
||||
{
|
||||
ClassNamespace = classNamespace;
|
||||
ClassName = className;
|
||||
ScriptType = scriptType;
|
||||
}
|
||||
};
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static void FrameCallback()
|
||||
{
|
||||
try
|
||||
{
|
||||
Dispatcher.DefaultGodotTaskScheduler?.Activate();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugUnhandledException(e);
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static unsafe IntPtr CreateManagedForGodotObjectBinding(godot_string_name* nativeTypeName,
|
||||
IntPtr godotObject)
|
||||
{
|
||||
try
|
||||
{
|
||||
Type nativeType = TypeGetProxyClass(nativeTypeName);
|
||||
var obj = (Object)FormatterServices.GetUninitializedObject(nativeType);
|
||||
|
||||
obj.NativePtr = godotObject;
|
||||
|
||||
var ctor = nativeType.GetConstructor(
|
||||
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
|
||||
null, Type.EmptyTypes, null);
|
||||
_ = ctor!.Invoke(obj, null);
|
||||
|
||||
return GCHandle.ToIntPtr(GCHandle.Alloc(obj));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static unsafe godot_bool CreateManagedForGodotObjectScriptInstance(IntPtr scriptPtr,
|
||||
IntPtr godotObject,
|
||||
godot_variant** args, int argCount)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Performance is not critical here as this will be replaced with source generators.
|
||||
Type scriptType = _scriptBridgeMap[scriptPtr];
|
||||
var obj = (Object)FormatterServices.GetUninitializedObject(scriptType);
|
||||
|
||||
obj.NativePtr = godotObject;
|
||||
|
||||
var ctor = scriptType
|
||||
.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
|
||||
.Where(c => c.GetParameters().Length == argCount)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (ctor == null)
|
||||
{
|
||||
if (argCount == 0)
|
||||
{
|
||||
throw new MissingMemberException(
|
||||
$"Cannot create script instance. The class '{scriptType.FullName}' does not define a parameterless constructor.");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new MissingMemberException(
|
||||
$"The class '{scriptType.FullName}' does not define a constructor that takes x parameters.");
|
||||
}
|
||||
}
|
||||
|
||||
var parameters = ctor.GetParameters();
|
||||
int paramCount = parameters.Length;
|
||||
|
||||
object[] invokeParams = new object[paramCount];
|
||||
|
||||
for (int i = 0; i < paramCount; i++)
|
||||
{
|
||||
invokeParams[i] = Marshaling.variant_to_mono_object_of_type(
|
||||
args[i], parameters[i].ParameterType);
|
||||
}
|
||||
|
||||
ctor.Invoke(obj, invokeParams);
|
||||
return true.ToGodotBool();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||
return false.ToGodotBool();
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static unsafe void GetScriptNativeName(IntPtr scriptPtr, godot_string_name* outRes)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Performance is not critical here as this will be replaced with source generators.
|
||||
if (!_scriptBridgeMap.TryGetValue(scriptPtr, out var scriptType))
|
||||
{
|
||||
*outRes = default;
|
||||
return;
|
||||
}
|
||||
|
||||
var native = Object.InternalGetClassNativeBase(scriptType);
|
||||
|
||||
var field = native?.GetField("NativeName", BindingFlags.DeclaredOnly | BindingFlags.Static |
|
||||
BindingFlags.Public | BindingFlags.NonPublic);
|
||||
|
||||
if (field == null)
|
||||
{
|
||||
*outRes = default;
|
||||
return;
|
||||
}
|
||||
|
||||
var nativeName = (StringName)field.GetValue(null);
|
||||
|
||||
if (nativeName == null)
|
||||
{
|
||||
*outRes = default;
|
||||
return;
|
||||
}
|
||||
|
||||
*outRes = NativeFuncs.godotsharp_string_name_new_copy(nativeName.NativeValue);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugUnhandledException(e);
|
||||
*outRes = default;
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static void SetGodotObjectPtr(IntPtr gcHandlePtr, IntPtr newPtr)
|
||||
{
|
||||
try
|
||||
{
|
||||
var target = (Object)GCHandle.FromIntPtr(gcHandlePtr).Target;
|
||||
if (target != null)
|
||||
target.NativePtr = newPtr;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugUnhandledException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static unsafe Type TypeGetProxyClass(godot_string_name* nativeTypeName)
|
||||
{
|
||||
// Performance is not critical here as this will be replaced with a generated dictionary.
|
||||
using var stringName = StringName.CreateTakingOwnershipOfDisposableValue(
|
||||
NativeFuncs.godotsharp_string_name_new_copy(nativeTypeName));
|
||||
string nativeTypeNameStr = stringName.ToString();
|
||||
|
||||
if (nativeTypeNameStr[0] == '_')
|
||||
nativeTypeNameStr = nativeTypeNameStr.Substring(1);
|
||||
|
||||
Type wrapperType = typeof(Object).Assembly.GetType("Godot." + nativeTypeNameStr);
|
||||
|
||||
if (wrapperType == null)
|
||||
{
|
||||
wrapperType = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.First(a => a.GetName().Name == "GodotSharpEditor")
|
||||
.GetType("Godot." + nativeTypeNameStr);
|
||||
}
|
||||
|
||||
static bool IsStatic(Type type) => type.IsAbstract && type.IsSealed;
|
||||
|
||||
if (wrapperType != null && IsStatic(wrapperType))
|
||||
{
|
||||
// A static class means this is a Godot singleton class. If an instance is needed we use Godot.Object.
|
||||
return typeof(Object);
|
||||
}
|
||||
|
||||
return wrapperType;
|
||||
}
|
||||
|
||||
// Called from GodotPlugins
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
private static void LookupScriptsInAssembly(Assembly assembly)
|
||||
{
|
||||
static void LookupScriptForClass(Type type)
|
||||
{
|
||||
var scriptPathAttr = type.GetCustomAttributes(inherit: false)
|
||||
.OfType<ScriptPathAttribute>()
|
||||
.FirstOrDefault();
|
||||
|
||||
if (scriptPathAttr == null)
|
||||
return;
|
||||
|
||||
_scriptLookupMap[scriptPathAttr.Path] = new ScriptLookupInfo(type.Namespace, type.Name, type);
|
||||
}
|
||||
|
||||
var assemblyHasScriptsAttr = assembly.GetCustomAttributes(inherit: false)
|
||||
.OfType<AssemblyHasScriptsAttribute>()
|
||||
.FirstOrDefault();
|
||||
|
||||
if (assemblyHasScriptsAttr == null)
|
||||
return;
|
||||
|
||||
if (assemblyHasScriptsAttr.RequiresLookup)
|
||||
{
|
||||
// This is supported for scenarios where specifying all types would be cumbersome,
|
||||
// such as when disabling C# source generators (for whatever reason) or when using a
|
||||
// language other than C# that has nothing similar to source generators to automate it.
|
||||
|
||||
var typeOfGodotObject = typeof(Object);
|
||||
|
||||
foreach (var type in assembly.GetTypes())
|
||||
{
|
||||
if (type.IsNested)
|
||||
continue;
|
||||
|
||||
if (!typeOfGodotObject.IsAssignableFrom(type))
|
||||
continue;
|
||||
|
||||
LookupScriptForClass(type);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is the most likely scenario as we use C# source generators
|
||||
|
||||
var scriptTypes = assemblyHasScriptsAttr.ScriptTypes;
|
||||
|
||||
if (scriptTypes != null)
|
||||
{
|
||||
for (int i = 0; i < scriptTypes.Length; i++)
|
||||
{
|
||||
LookupScriptForClass(scriptTypes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static unsafe void RaiseEventSignal(IntPtr ownerGCHandlePtr,
|
||||
godot_string_name* eventSignalName, godot_variant** args, int argCount, godot_bool* outOwnerIsNull)
|
||||
{
|
||||
try
|
||||
{
|
||||
var owner = (Object)GCHandle.FromIntPtr(ownerGCHandlePtr).Target;
|
||||
|
||||
if (owner == null)
|
||||
{
|
||||
*outOwnerIsNull = true.ToGodotBool();
|
||||
return;
|
||||
}
|
||||
|
||||
*outOwnerIsNull = false.ToGodotBool();
|
||||
|
||||
owner.InternalRaiseEventSignal(eventSignalName, args, argCount);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||
*outOwnerIsNull = false.ToGodotBool();
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static unsafe void GetScriptSignalList(IntPtr scriptPtr, godot_dictionary* outRetSignals)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Performance is not critical here as this will be replaced with source generators.
|
||||
using var signals = new Dictionary();
|
||||
|
||||
Type top = _scriptBridgeMap[scriptPtr];
|
||||
Type native = Object.InternalGetClassNativeBase(top);
|
||||
|
||||
while (top != null && top != native)
|
||||
{
|
||||
// Legacy signals
|
||||
|
||||
foreach (var signalDelegate in top
|
||||
.GetNestedTypes(BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public)
|
||||
.Where(nestedType => typeof(Delegate).IsAssignableFrom(nestedType))
|
||||
.Where(@delegate => @delegate.GetCustomAttributes().OfType<SignalAttribute>().Any()))
|
||||
{
|
||||
var invokeMethod = signalDelegate.GetMethod("Invoke");
|
||||
|
||||
if (invokeMethod == null)
|
||||
throw new MissingMethodException(signalDelegate.FullName, "Invoke");
|
||||
|
||||
var signalParams = new Collections.Array();
|
||||
|
||||
foreach (var parameters in invokeMethod.GetParameters())
|
||||
{
|
||||
var paramType = Marshaling.managed_to_variant_type(
|
||||
parameters.ParameterType, out bool nilIsVariant);
|
||||
signalParams.Add(new Dictionary()
|
||||
{
|
||||
{ "name", parameters.Name },
|
||||
{ "type", paramType },
|
||||
{ "nil_is_variant", nilIsVariant }
|
||||
});
|
||||
}
|
||||
|
||||
signals.Add(signalDelegate.Name, signalParams);
|
||||
}
|
||||
|
||||
// Event signals
|
||||
|
||||
var foundEventSignals = top.GetEvents(
|
||||
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||
BindingFlags.NonPublic | BindingFlags.Public)
|
||||
.Where(ev => ev.GetCustomAttributes().OfType<SignalAttribute>().Any())
|
||||
.Select(ev => ev.Name);
|
||||
|
||||
var fields = top.GetFields(
|
||||
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||
BindingFlags.NonPublic | BindingFlags.Public);
|
||||
|
||||
foreach (var eventSignalField in fields
|
||||
.Where(f => typeof(Delegate).IsAssignableFrom(f.FieldType))
|
||||
.Where(f => foundEventSignals.Contains(f.Name)))
|
||||
{
|
||||
var delegateType = eventSignalField.FieldType;
|
||||
var invokeMethod = delegateType.GetMethod("Invoke");
|
||||
|
||||
if (invokeMethod == null)
|
||||
throw new MissingMethodException(delegateType.FullName, "Invoke");
|
||||
|
||||
var signalParams = new Collections.Array();
|
||||
|
||||
foreach (var parameters in invokeMethod.GetParameters())
|
||||
{
|
||||
var paramType = Marshaling.managed_to_variant_type(
|
||||
parameters.ParameterType, out bool nilIsVariant);
|
||||
signalParams.Add(new Dictionary()
|
||||
{
|
||||
{ "name", parameters.Name },
|
||||
{ "type", paramType },
|
||||
{ "nil_is_variant", nilIsVariant }
|
||||
});
|
||||
}
|
||||
|
||||
signals.Add(eventSignalField.Name, signalParams);
|
||||
}
|
||||
|
||||
top = top.BaseType;
|
||||
}
|
||||
|
||||
*outRetSignals = NativeFuncs.godotsharp_dictionary_new_copy(signals.NativeValue);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugUnhandledException(e);
|
||||
*outRetSignals = NativeFuncs.godotsharp_dictionary_new();
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static unsafe godot_bool HasScriptSignal(IntPtr scriptPtr, godot_string* signalName)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Performance is not critical here as this will be replaced with source generators.
|
||||
using var signals = new Dictionary();
|
||||
|
||||
string signalNameStr = Marshaling.mono_string_from_godot(*signalName);
|
||||
|
||||
Type top = _scriptBridgeMap[scriptPtr];
|
||||
Type native = Object.InternalGetClassNativeBase(top);
|
||||
|
||||
while (top != null && top != native)
|
||||
{
|
||||
// Legacy signals
|
||||
|
||||
if (top
|
||||
.GetNestedTypes(BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public)
|
||||
.Where(nestedType => typeof(Delegate).IsAssignableFrom(nestedType))
|
||||
.Where(@delegate => @delegate.GetCustomAttributes().OfType<SignalAttribute>().Any())
|
||||
.Any(signalDelegate => signalDelegate.Name == signalNameStr)
|
||||
)
|
||||
{
|
||||
return true.ToGodotBool();
|
||||
}
|
||||
|
||||
// Event signals
|
||||
|
||||
if (top.GetEvents(
|
||||
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||
BindingFlags.NonPublic | BindingFlags.Public)
|
||||
.Where(ev => ev.GetCustomAttributes().OfType<SignalAttribute>().Any())
|
||||
.Any(eventSignal => eventSignal.Name == signalNameStr)
|
||||
)
|
||||
{
|
||||
return true.ToGodotBool();
|
||||
}
|
||||
|
||||
top = top.BaseType;
|
||||
}
|
||||
|
||||
return false.ToGodotBool();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugUnhandledException(e);
|
||||
return false.ToGodotBool();
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static unsafe godot_bool HasMethodUnknownParams(IntPtr scriptPtr, godot_string* method,
|
||||
godot_bool deep)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Performance is not critical here as this will be replaced with source generators.
|
||||
if (!_scriptBridgeMap.TryGetValue(scriptPtr, out var scriptType))
|
||||
return false.ToGodotBool();
|
||||
|
||||
string methodStr = Marshaling.mono_string_from_godot(*method);
|
||||
|
||||
if (deep.ToBool())
|
||||
{
|
||||
Type top = scriptType;
|
||||
Type native = Object.InternalGetClassNativeBase(scriptType);
|
||||
|
||||
while (top != null && top != native)
|
||||
{
|
||||
var methodInfo = top.GetMethod(methodStr,
|
||||
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||
BindingFlags.NonPublic | BindingFlags.Public);
|
||||
|
||||
if (methodInfo != null)
|
||||
return true.ToGodotBool();
|
||||
|
||||
top = top.BaseType;
|
||||
}
|
||||
|
||||
top = native;
|
||||
Type typeOfSystemObject = typeof(System.Object);
|
||||
while (top != null && top != typeOfSystemObject)
|
||||
{
|
||||
bool found = top.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||
BindingFlags.NonPublic | BindingFlags.Public)
|
||||
.Where(m => m.GetCustomAttributes(false).OfType<GodotMethodAttribute>()
|
||||
.Where(a => a.MethodName == methodStr)
|
||||
.Any())
|
||||
.Any();
|
||||
|
||||
if (found)
|
||||
return true.ToGodotBool();
|
||||
|
||||
top = top.BaseType;
|
||||
}
|
||||
|
||||
return false.ToGodotBool();
|
||||
}
|
||||
else
|
||||
{
|
||||
var methodInfo = scriptType.GetMethod(methodStr, BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||
BindingFlags.NonPublic | BindingFlags.Public);
|
||||
return (methodInfo != null).ToGodotBool();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugUnhandledException(e);
|
||||
return false.ToGodotBool();
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static godot_bool ScriptIsOrInherits(IntPtr scriptPtr, IntPtr scriptPtrMaybeBase)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_scriptBridgeMap.TryGetValue(scriptPtr, out var scriptType))
|
||||
return false.ToGodotBool();
|
||||
|
||||
if (!_scriptBridgeMap.TryGetValue(scriptPtrMaybeBase, out var maybeBaseType))
|
||||
return false.ToGodotBool();
|
||||
|
||||
return (scriptType == maybeBaseType || maybeBaseType.IsAssignableFrom(scriptType)).ToGodotBool();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugUnhandledException(e);
|
||||
return false.ToGodotBool();
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static unsafe godot_bool AddScriptBridge(IntPtr scriptPtr, godot_string* scriptPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
string scriptPathStr = Marshaling.mono_string_from_godot(*scriptPath);
|
||||
|
||||
if (!_scriptLookupMap.TryGetValue(scriptPathStr, out var lookupInfo))
|
||||
return false.ToGodotBool();
|
||||
|
||||
_scriptBridgeMap.Add(scriptPtr, lookupInfo.ScriptType);
|
||||
|
||||
return true.ToGodotBool();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugUnhandledException(e);
|
||||
return false.ToGodotBool();
|
||||
}
|
||||
}
|
||||
|
||||
internal static void AddScriptBridgeWithType(IntPtr scriptPtr, Type scriptType)
|
||||
=> _scriptBridgeMap.Add(scriptPtr, scriptType);
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static void RemoveScriptBridge(IntPtr scriptPtr)
|
||||
{
|
||||
try
|
||||
{
|
||||
_scriptBridgeMap.Remove(scriptPtr);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugUnhandledException(e);
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static unsafe void UpdateScriptClassInfo(IntPtr scriptPtr, godot_bool* outTool,
|
||||
godot_dictionary* outRpcFunctionsDest)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Performance is not critical here as this will be replaced with source generators.
|
||||
var scriptType = _scriptBridgeMap[scriptPtr];
|
||||
|
||||
*outTool = scriptType.GetCustomAttributes(inherit: false)
|
||||
.OfType<ToolAttribute>()
|
||||
.Any().ToGodotBool();
|
||||
|
||||
if (!(*outTool).ToBool() && scriptType.IsNested)
|
||||
{
|
||||
*outTool = (scriptType.DeclaringType?.GetCustomAttributes(inherit: false)
|
||||
.OfType<ToolAttribute>()
|
||||
.Any() ?? false).ToGodotBool();
|
||||
}
|
||||
|
||||
if (!(*outTool).ToBool() && scriptType.Assembly.GetName().Name == "GodotTools")
|
||||
*outTool = true.ToGodotBool();
|
||||
|
||||
// RPC functions
|
||||
|
||||
static MultiplayerAPI.RPCMode MemberGetRpcMode(MemberInfo memberInfo)
|
||||
{
|
||||
if (memberInfo.GetCustomAttributes(inherit: false).OfType<RemoteAttribute>().Any())
|
||||
return MultiplayerAPI.RPCMode.Remote;
|
||||
|
||||
if (memberInfo.GetCustomAttributes(inherit: false).OfType<MasterAttribute>().Any())
|
||||
return MultiplayerAPI.RPCMode.Master;
|
||||
|
||||
if (memberInfo.GetCustomAttributes(inherit: false).OfType<PuppetAttribute>().Any())
|
||||
return MultiplayerAPI.RPCMode.Puppet;
|
||||
|
||||
return MultiplayerAPI.RPCMode.Disabled;
|
||||
}
|
||||
|
||||
Dictionary<string, Dictionary> rpcFunctions = new();
|
||||
|
||||
Type top = _scriptBridgeMap[scriptPtr];
|
||||
Type native = Object.InternalGetClassNativeBase(top);
|
||||
|
||||
while (top != null && top != native)
|
||||
{
|
||||
foreach (var method in top.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||
BindingFlags.NonPublic | BindingFlags.Public))
|
||||
{
|
||||
if (method.IsStatic)
|
||||
continue;
|
||||
|
||||
string methodName = method.Name;
|
||||
|
||||
if (rpcFunctions.ContainsKey(methodName))
|
||||
continue;
|
||||
|
||||
var rpcMode = MemberGetRpcMode(method);
|
||||
|
||||
if (rpcMode == MultiplayerAPI.RPCMode.Disabled)
|
||||
continue;
|
||||
|
||||
var rpcConfig = new Dictionary();
|
||||
rpcConfig["rpc_mode"] = (int)rpcMode;
|
||||
// TODO Transfer mode, channel
|
||||
rpcConfig["transfer_mode"] = (int)MultiplayerPeer.TransferModeEnum.Reliable;
|
||||
rpcConfig["channel"] = 0;
|
||||
|
||||
rpcFunctions.Add(methodName, rpcConfig);
|
||||
}
|
||||
|
||||
top = top.BaseType;
|
||||
}
|
||||
|
||||
*outRpcFunctionsDest =
|
||||
NativeFuncs.godotsharp_dictionary_new_copy(((Dictionary)rpcFunctions).NativeValue);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugUnhandledException(e);
|
||||
*outTool = false.ToGodotBool();
|
||||
*outRpcFunctionsDest = NativeFuncs.godotsharp_dictionary_new();
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static unsafe godot_bool SwapGCHandleForType(IntPtr oldGCHandlePtr, IntPtr* outNewGCHandlePtr,
|
||||
godot_bool createWeak)
|
||||
{
|
||||
try
|
||||
{
|
||||
var oldGCHandle = GCHandle.FromIntPtr(oldGCHandlePtr);
|
||||
|
||||
object target = oldGCHandle.Target;
|
||||
|
||||
if (target == null)
|
||||
{
|
||||
*outNewGCHandlePtr = IntPtr.Zero;
|
||||
return false.ToGodotBool(); // Called after the managed side was collected, so nothing to do here
|
||||
}
|
||||
|
||||
// Release the current weak handle and replace it with a strong handle.
|
||||
var newGCHandle = GCHandle.Alloc(target,
|
||||
createWeak.ToBool() ? GCHandleType.Weak : GCHandleType.Normal);
|
||||
*outNewGCHandlePtr = GCHandle.ToIntPtr(newGCHandle);
|
||||
|
||||
return true.ToGodotBool();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugUnhandledException(e);
|
||||
*outNewGCHandlePtr = IntPtr.Zero;
|
||||
return false.ToGodotBool();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
namespace Godot
|
||||
{
|
||||
|
@ -19,13 +21,23 @@ namespace Godot
|
|||
sb.Append(" ");
|
||||
}
|
||||
|
||||
public static void InstallTraceListener()
|
||||
[UnmanagedCallersOnly]
|
||||
internal static void InstallTraceListener()
|
||||
{
|
||||
try
|
||||
{
|
||||
Trace.Listeners.Clear();
|
||||
Trace.Listeners.Add(new GodotTraceListener());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||
ExceptionUtils.PushError("Failed to install 'System.Diagnostics.Trace' listener.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void GetStackFrameInfo(StackFrame frame, out string fileName, out int fileLineNumber, out string methodDecl)
|
||||
public static void GetStackFrameInfo(StackFrame frame, out string fileName, out int fileLineNumber,
|
||||
out string methodDecl)
|
||||
{
|
||||
fileName = frame.GetFileName();
|
||||
fileLineNumber = frame.GetFileLineNumber();
|
||||
|
|
|
@ -4,11 +4,67 @@ 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
|
||||
{
|
||||
[UnmanagedCallersOnly]
|
||||
internal static godot_bool DelegateEquals(IntPtr delegateGCHandleA, IntPtr delegateGCHandleB)
|
||||
{
|
||||
try
|
||||
{
|
||||
var @delegateA = (Delegate)GCHandle.FromIntPtr(delegateGCHandleA).Target;
|
||||
var @delegateB = (Delegate)GCHandle.FromIntPtr(delegateGCHandleB).Target;
|
||||
return (@delegateA == @delegateB).ToGodotBool();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugUnhandledException(e);
|
||||
return false.ToGodotBool();
|
||||
}
|
||||
}
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static unsafe void InvokeWithVariantArgs(IntPtr delegateGCHandle, godot_variant** args, uint argc,
|
||||
godot_variant* outRet)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 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);
|
||||
|
||||
*outRet = Marshaling.mono_object_to_variant(invokeRet);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||
*outRet = default;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Check if we should be using BindingFlags.DeclaredOnly (would give better reflection performance).
|
||||
|
||||
private enum TargetKind : uint
|
||||
{
|
||||
Static,
|
||||
|
@ -16,7 +72,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 +131,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 +154,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 +274,14 @@ 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 +345,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;
|
||||
|
@ -313,7 +383,8 @@ namespace Godot
|
|||
int valueBufferLength = reader.ReadInt32();
|
||||
byte[] valueBuffer = reader.ReadBytes(valueBufferLength);
|
||||
|
||||
FieldInfo fieldInfo = targetType.GetField(name, BindingFlags.Instance | BindingFlags.Public);
|
||||
FieldInfo fieldInfo =
|
||||
targetType.GetField(name, BindingFlags.Instance | BindingFlags.Public);
|
||||
fieldInfo?.SetValue(recreatedTarget, GD.Bytes2Var(valueBuffer));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,49 +1,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;
|
||||
public godot_dictionary NativeValue;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new empty <see cref="Dictionary"/>.
|
||||
/// </summary>
|
||||
public Dictionary()
|
||||
{
|
||||
safeHandle = new DictionarySafeHandle(godot_icall_Dictionary_Ctor());
|
||||
NativeValue = NativeFuncs.godotsharp_dictionary_new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -60,22 +39,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 +58,14 @@ namespace Godot.Collections
|
|||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (disposed)
|
||||
return;
|
||||
|
||||
if (safeHandle != null)
|
||||
{
|
||||
safeHandle.Dispose();
|
||||
safeHandle = null;
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
disposed = true;
|
||||
public void Dispose(bool disposing)
|
||||
{
|
||||
// Always dispose `NativeValue` even if disposing is true
|
||||
NativeValue.Dispose();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -102,7 +75,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;
|
||||
NativeFuncs.godotsharp_dictionary_duplicate(ref NativeValue, deep.ToGodotBool(), out newDictionary);
|
||||
return CreateTakingOwnershipOfDisposableValue(newDictionary);
|
||||
}
|
||||
|
||||
// IDictionary
|
||||
|
@ -114,8 +89,9 @@ namespace Godot.Collections
|
|||
{
|
||||
get
|
||||
{
|
||||
IntPtr handle = godot_icall_Dictionary_Keys(GetPtr());
|
||||
return new Array(new ArraySafeHandle(handle));
|
||||
godot_array keysArray;
|
||||
NativeFuncs.godotsharp_dictionary_keys(ref NativeValue, out keysArray);
|
||||
return Array.CreateTakingOwnershipOfDisposableValue(keysArray);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,16 +102,24 @@ namespace Godot.Collections
|
|||
{
|
||||
get
|
||||
{
|
||||
IntPtr handle = godot_icall_Dictionary_Values(GetPtr());
|
||||
return new Array(new ArraySafeHandle(handle));
|
||||
godot_array valuesArray;
|
||||
NativeFuncs.godotsharp_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;
|
||||
NativeFuncs.godotsharp_dictionary_keys(ref NativeValue, out keysArray);
|
||||
var keys = Array.CreateTakingOwnershipOfDisposableValue(keysArray);
|
||||
|
||||
godot_array valuesArray;
|
||||
NativeFuncs.godotsharp_dictionary_keys(ref NativeValue, out valuesArray);
|
||||
var values = Array.CreateTakingOwnershipOfDisposableValue(valuesArray);
|
||||
|
||||
int count = NativeFuncs.godotsharp_dictionary_count(ref NativeValue);
|
||||
|
||||
return (keys, values, count);
|
||||
}
|
||||
|
||||
|
@ -147,10 +131,28 @@ namespace Godot.Collections
|
|||
/// Returns the object at the given <paramref name="key"/>.
|
||||
/// </summary>
|
||||
/// <value>The object at the given <paramref name="key"/>.</value>
|
||||
public object this[object key]
|
||||
public unsafe object this[object key]
|
||||
{
|
||||
get => godot_icall_Dictionary_GetValue(GetPtr(), key);
|
||||
set => godot_icall_Dictionary_SetValue(GetPtr(), key, value);
|
||||
get
|
||||
{
|
||||
using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
|
||||
if (NativeFuncs.godotsharp_dictionary_try_get_value(ref NativeValue, &variantKey,
|
||||
out godot_variant value).ToBool())
|
||||
{
|
||||
using (value)
|
||||
return Marshaling.variant_to_mono_object(&value);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new KeyNotFoundException();
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
|
||||
using godot_variant variantValue = Marshaling.mono_object_to_variant(value);
|
||||
NativeFuncs.godotsharp_dictionary_set_value(ref NativeValue, &variantKey, &variantValue);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -159,19 +161,32 @@ 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 unsafe void Add(object key, object value)
|
||||
{
|
||||
using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
|
||||
|
||||
if (NativeFuncs.godotsharp_dictionary_contains_key(ref NativeValue, &variantKey).ToBool())
|
||||
throw new ArgumentException("An element with the same key already exists", nameof(key));
|
||||
|
||||
using godot_variant variantValue = Marshaling.mono_object_to_variant(value);
|
||||
NativeFuncs.godotsharp_dictionary_add(ref NativeValue, &variantKey, &variantValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Erases all items from this <see cref="Dictionary"/>.
|
||||
/// </summary>
|
||||
public void Clear() => godot_icall_Dictionary_Clear(GetPtr());
|
||||
public void Clear() => NativeFuncs.godotsharp_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 unsafe bool Contains(object key)
|
||||
{
|
||||
using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
|
||||
return NativeFuncs.godotsharp_dictionary_contains_key(ref NativeValue, &variantKey).ToBool();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an enumerator for this <see cref="Dictionary"/>.
|
||||
|
@ -183,7 +198,11 @@ 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 unsafe void Remove(object key)
|
||||
{
|
||||
using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
|
||||
NativeFuncs.godotsharp_dictionary_remove_key(ref NativeValue, &variantKey);
|
||||
}
|
||||
|
||||
// ICollection
|
||||
|
||||
|
@ -196,7 +215,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 => NativeFuncs.godotsharp_dictionary_count(ref NativeValue);
|
||||
|
||||
/// <summary>
|
||||
/// Copies the elements of this <see cref="Dictionary"/> to the given
|
||||
|
@ -210,12 +229,14 @@ namespace Godot.Collections
|
|||
throw new ArgumentNullException(nameof(array), "Value cannot be null.");
|
||||
|
||||
if (index < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(index), "Number was less than the array's lower bound in the first dimension.");
|
||||
throw new ArgumentOutOfRangeException(nameof(index),
|
||||
"Number was less than the array's lower bound in the first dimension.");
|
||||
|
||||
var (keys, values, count) = GetKeyValuePairs();
|
||||
|
||||
if (array.Length < (index + count))
|
||||
throw new ArgumentException("Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
|
||||
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++)
|
||||
{
|
||||
|
@ -253,15 +274,23 @@ namespace Godot.Collections
|
|||
{
|
||||
UpdateEntry();
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateEntry()
|
||||
private unsafe void UpdateEntry()
|
||||
{
|
||||
dirty = false;
|
||||
godot_icall_Dictionary_KeyValuePairAt(dictionary.GetPtr(), index, out object key, out object value);
|
||||
entry = new DictionaryEntry(key, value);
|
||||
NativeFuncs.godotsharp_dictionary_key_value_pair_at(ref dictionary.NativeValue, index,
|
||||
out godot_variant key,
|
||||
out godot_variant value);
|
||||
using (key)
|
||||
using (value)
|
||||
{
|
||||
entry = new DictionaryEntry(Marshaling.variant_to_mono_object(&key),
|
||||
Marshaling.variant_to_mono_object(&value));
|
||||
}
|
||||
}
|
||||
|
||||
public object Key => Entry.Key;
|
||||
|
@ -286,75 +315,23 @@ namespace Godot.Collections
|
|||
/// Converts this <see cref="Dictionary"/> to a string.
|
||||
/// </summary>
|
||||
/// <returns>A string representation of this dictionary.</returns>
|
||||
public override string ToString()
|
||||
public override unsafe string ToString()
|
||||
{
|
||||
return godot_icall_Dictionary_ToString(GetPtr());
|
||||
using godot_string str = default;
|
||||
NativeFuncs.godotsharp_dictionary_to_string(ref NativeValue, &str);
|
||||
return Marshaling.mono_string_from_godot(str);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static IntPtr godot_icall_Dictionary_Ctor();
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Dictionary_Dtor(IntPtr ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static object godot_icall_Dictionary_GetValue(IntPtr ptr, object key);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static object godot_icall_Dictionary_GetValue_Generic(IntPtr ptr, object key, int valTypeEncoding, IntPtr valTypeClass);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Dictionary_SetValue(IntPtr ptr, object key, object value);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static IntPtr godot_icall_Dictionary_Keys(IntPtr ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static IntPtr godot_icall_Dictionary_Values(IntPtr ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static int godot_icall_Dictionary_Count(IntPtr ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static int godot_icall_Dictionary_KeyValuePairs(IntPtr ptr, out IntPtr keys, out IntPtr values);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Dictionary_KeyValuePairAt(IntPtr ptr, int index, out object key, out object value);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Dictionary_Add(IntPtr ptr, object key, object value);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_Dictionary_Clear(IntPtr ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static bool godot_icall_Dictionary_Contains(IntPtr ptr, object key, object value);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static bool godot_icall_Dictionary_ContainsKey(IntPtr ptr, object key);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static IntPtr godot_icall_Dictionary_Duplicate(IntPtr ptr, bool deep);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static bool godot_icall_Dictionary_RemoveKey(IntPtr ptr, object key);
|
||||
|
||||
[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 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 +340,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 +373,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 +389,13 @@ 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 +403,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 +413,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 +424,24 @@ 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
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
|
||||
if (NativeFuncs.godotsharp_dictionary_try_get_value(ref _underlyingDict.NativeValue,
|
||||
&variantKey, out godot_variant value).ToBool())
|
||||
{
|
||||
using (value)
|
||||
return (TValue)Marshaling.variant_to_mono_object_of_type(&value, TypeOfValues);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new KeyNotFoundException();
|
||||
}
|
||||
}
|
||||
}
|
||||
set => _underlyingDict[key] = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -469,8 +451,9 @@ namespace Godot.Collections
|
|||
{
|
||||
get
|
||||
{
|
||||
IntPtr handle = Dictionary.godot_icall_Dictionary_Keys(objectDict.GetPtr());
|
||||
return new Array<TKey>(new ArraySafeHandle(handle));
|
||||
godot_array keyArray;
|
||||
NativeFuncs.godotsharp_dictionary_keys(ref _underlyingDict.NativeValue, out keyArray);
|
||||
return Array<TKey>.CreateTakingOwnershipOfDisposableValue(keyArray);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -481,15 +464,23 @@ namespace Godot.Collections
|
|||
{
|
||||
get
|
||||
{
|
||||
IntPtr handle = Dictionary.godot_icall_Dictionary_Values(objectDict.GetPtr());
|
||||
return new Array<TValue>(new ArraySafeHandle(handle));
|
||||
godot_array valuesArray;
|
||||
NativeFuncs.godotsharp_dictionary_values(ref _underlyingDict.NativeValue, out valuesArray);
|
||||
return Array<TValue>.CreateTakingOwnershipOfDisposableValue(valuesArray);
|
||||
}
|
||||
}
|
||||
|
||||
private KeyValuePair<TKey, TValue> GetKeyValuePair(int index)
|
||||
private unsafe KeyValuePair<TKey, TValue> GetKeyValuePair(int index)
|
||||
{
|
||||
Dictionary.godot_icall_Dictionary_KeyValuePairAt(GetPtr(), index, out object key, out object value);
|
||||
return new KeyValuePair<TKey, TValue>((TKey)key, (TValue)value);
|
||||
NativeFuncs.godotsharp_dictionary_key_value_pair_at(ref _underlyingDict.NativeValue, index,
|
||||
out godot_variant key,
|
||||
out godot_variant value);
|
||||
using (key)
|
||||
using (value)
|
||||
{
|
||||
return new KeyValuePair<TKey, TValue>((TKey)Marshaling.variant_to_mono_object(&key),
|
||||
(TValue)Marshaling.variant_to_mono_object(&value));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -500,7 +491,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,16 +501,17 @@ 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>
|
||||
/// Removes an element from this <see cref="Dictionary{TKey, TValue}"/> by key.
|
||||
/// </summary>
|
||||
/// <param name="key">The key of the element to remove.</param>
|
||||
public bool Remove(TKey key)
|
||||
public unsafe bool Remove(TKey key)
|
||||
{
|
||||
return Dictionary.godot_icall_Dictionary_RemoveKey(GetPtr(), key);
|
||||
using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
|
||||
return NativeFuncs.godotsharp_dictionary_remove_key(ref _underlyingDict.NativeValue, &variantKey).ToBool();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -528,10 +520,19 @@ namespace Godot.Collections
|
|||
/// <param name="key">The key of the element to get.</param>
|
||||
/// <param name="value">The value at the given <paramref name="key"/>.</param>
|
||||
/// <returns>If an object was found for the given <paramref name="key"/>.</returns>
|
||||
public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
|
||||
public unsafe 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;
|
||||
using godot_variant variantKey = Marshaling.mono_object_to_variant(key);
|
||||
bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref _underlyingDict.NativeValue,
|
||||
&variantKey, out godot_variant retValue).ToBool();
|
||||
|
||||
using (retValue)
|
||||
{
|
||||
value = found ?
|
||||
(TValue)Marshaling.variant_to_mono_object_of_type(&retValue, TypeOfValues) :
|
||||
default;
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
@ -542,16 +543,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 +557,22 @@ namespace Godot.Collections
|
|||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
objectDict.Clear();
|
||||
_underlyingDict.Clear();
|
||||
}
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
|
||||
unsafe bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
return objectDict.Contains(new KeyValuePair<object, object>(item.Key, item.Value));
|
||||
using godot_variant variantKey = Marshaling.mono_object_to_variant(item.Key);
|
||||
bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref _underlyingDict.NativeValue,
|
||||
&variantKey, out godot_variant retValue).ToBool();
|
||||
|
||||
using (retValue)
|
||||
{
|
||||
if (!found)
|
||||
return false;
|
||||
|
||||
return NativeFuncs.godotsharp_variant_equals(&variantKey, &retValue).ToBool();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -579,12 +587,14 @@ namespace Godot.Collections
|
|||
throw new ArgumentNullException(nameof(array), "Value cannot be null.");
|
||||
|
||||
if (arrayIndex < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(arrayIndex), "Number was less than the array's lower bound in the first dimension.");
|
||||
throw new ArgumentOutOfRangeException(nameof(arrayIndex),
|
||||
"Number was less than the array's lower bound in the first dimension.");
|
||||
|
||||
int count = 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.");
|
||||
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++)
|
||||
{
|
||||
|
@ -593,10 +603,25 @@ namespace Godot.Collections
|
|||
}
|
||||
}
|
||||
|
||||
bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
|
||||
unsafe bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
|
||||
{
|
||||
return Dictionary.godot_icall_Dictionary_Remove(GetPtr(), item.Key, item.Value);
|
||||
;
|
||||
using godot_variant variantKey = Marshaling.mono_object_to_variant(item.Key);
|
||||
bool found = NativeFuncs.godotsharp_dictionary_try_get_value(ref _underlyingDict.NativeValue,
|
||||
&variantKey, out godot_variant retValue).ToBool();
|
||||
|
||||
using (retValue)
|
||||
{
|
||||
if (!found)
|
||||
return false;
|
||||
|
||||
if (NativeFuncs.godotsharp_variant_equals(&variantKey, &retValue).ToBool())
|
||||
{
|
||||
return NativeFuncs.godotsharp_dictionary_remove_key(
|
||||
ref _underlyingDict.NativeValue, &variantKey).ToBool();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// IEnumerable<KeyValuePair<TKey, TValue>>
|
||||
|
@ -613,15 +638,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,13 +1,26 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
namespace Godot
|
||||
{
|
||||
public static class Dispatcher
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern GodotTaskScheduler godot_icall_DefaultGodotTaskScheduler();
|
||||
internal static GodotTaskScheduler DefaultGodotTaskScheduler;
|
||||
|
||||
public static GodotSynchronizationContext SynchronizationContext =>
|
||||
godot_icall_DefaultGodotTaskScheduler().Context;
|
||||
[UnmanagedCallersOnly]
|
||||
internal static void InitializeDefaultGodotTaskScheduler()
|
||||
{
|
||||
try
|
||||
{
|
||||
DefaultGodotTaskScheduler = new GodotTaskScheduler();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugUnhandledException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static GodotSynchronizationContext SynchronizationContext => DefaultGodotTaskScheduler.Context;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,212 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using System.Linq.Expressions;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Godot
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an <see cref="Godot.Object"/> whose members can be dynamically accessed at runtime through the Variant API.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The <see cref="Godot.DynamicGodotObject"/> class enables access to the Variant
|
||||
/// members of a <see cref="Godot.Object"/> instance at runtime.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This allows accessing the class members using their original names in the engine as well as the members from the
|
||||
/// script attached to the <see cref="Godot.Object"/>, regardless of the scripting language it was written in.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// This sample shows how to use <see cref="Godot.DynamicGodotObject"/> to dynamically access the engine members of a <see cref="Godot.Object"/>.
|
||||
/// <code>
|
||||
/// dynamic sprite = GetNode("Sprite2D").DynamicGodotObject;
|
||||
/// sprite.add_child(this);
|
||||
///
|
||||
/// if ((sprite.hframes * sprite.vframes) > 0)
|
||||
/// sprite.frame = 0;
|
||||
/// </code>
|
||||
/// </example>
|
||||
/// <example>
|
||||
/// This sample shows how to use <see cref="Godot.DynamicGodotObject"/> to dynamically access the members of the script attached to a <see cref="Godot.Object"/>.
|
||||
/// <code>
|
||||
/// dynamic childNode = GetNode("ChildNode").DynamicGodotObject;
|
||||
///
|
||||
/// if (childNode.print_allowed)
|
||||
/// {
|
||||
/// childNode.message = "Hello from C#";
|
||||
/// childNode.print_message(3);
|
||||
/// }
|
||||
/// </code>
|
||||
/// The <c>ChildNode</c> node has the following GDScript script attached:
|
||||
/// <code>
|
||||
/// // # ChildNode.gd
|
||||
/// // var print_allowed = true
|
||||
/// // var message = ""
|
||||
/// //
|
||||
/// // func print_message(times):
|
||||
/// // for i in times:
|
||||
/// // print(message)
|
||||
/// </code>
|
||||
/// </example>
|
||||
public class DynamicGodotObject : DynamicObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Godot.Object"/> associated with this <see cref="Godot.DynamicGodotObject"/>.
|
||||
/// </summary>
|
||||
public Object Value { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Godot.DynamicGodotObject"/> class.
|
||||
/// </summary>
|
||||
/// <param name="godotObject">
|
||||
/// The <see cref="Godot.Object"/> that will be associated with this <see cref="Godot.DynamicGodotObject"/>.
|
||||
/// </param>
|
||||
/// <exception cref="System.ArgumentNullException">
|
||||
/// Thrown when the <paramref name="godotObject"/> parameter is null.
|
||||
/// </exception>
|
||||
public DynamicGodotObject(Object godotObject)
|
||||
{
|
||||
if (godotObject == null)
|
||||
throw new ArgumentNullException(nameof(godotObject));
|
||||
|
||||
this.Value = godotObject;
|
||||
}
|
||||
|
||||
public override IEnumerable<string> GetDynamicMemberNames()
|
||||
{
|
||||
return godot_icall_DynamicGodotObject_SetMemberList(Object.GetPtr(Value));
|
||||
}
|
||||
|
||||
public override bool TryBinaryOperation(BinaryOperationBinder binder, object arg, out object result)
|
||||
{
|
||||
switch (binder.Operation)
|
||||
{
|
||||
case ExpressionType.Equal:
|
||||
case ExpressionType.NotEqual:
|
||||
if (binder.ReturnType == typeof(bool) || binder.ReturnType.IsAssignableFrom(typeof(bool)))
|
||||
{
|
||||
if (arg == null)
|
||||
{
|
||||
bool boolResult = Object.IsInstanceValid(Value);
|
||||
|
||||
if (binder.Operation == ExpressionType.Equal)
|
||||
boolResult = !boolResult;
|
||||
|
||||
result = boolResult;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (arg is Object other)
|
||||
{
|
||||
bool boolResult = (Value == other);
|
||||
|
||||
if (binder.Operation == ExpressionType.NotEqual)
|
||||
boolResult = !boolResult;
|
||||
|
||||
result = boolResult;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
// We're not implementing operators <, <=, >, and >= (LessThan, LessThanOrEqual, GreaterThan, GreaterThanOrEqual).
|
||||
// These are used on the actual pointers in variant_op.cpp. It's better to let the user do that explicitly.
|
||||
break;
|
||||
}
|
||||
|
||||
return base.TryBinaryOperation(binder, arg, out result);
|
||||
}
|
||||
|
||||
public override bool TryConvert(ConvertBinder binder, out object result)
|
||||
{
|
||||
if (binder.Type == typeof(Object))
|
||||
{
|
||||
result = Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeof(Object).IsAssignableFrom(binder.Type))
|
||||
{
|
||||
// Throws InvalidCastException when the cast fails
|
||||
result = Convert.ChangeType(Value, binder.Type);
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.TryConvert(binder, out result);
|
||||
}
|
||||
|
||||
public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
|
||||
{
|
||||
if (indexes.Length == 1)
|
||||
{
|
||||
if (indexes[0] is string name)
|
||||
{
|
||||
return godot_icall_DynamicGodotObject_GetMember(Object.GetPtr(Value), name, out result);
|
||||
}
|
||||
}
|
||||
|
||||
return base.TryGetIndex(binder, indexes, out result);
|
||||
}
|
||||
|
||||
public override bool TryGetMember(GetMemberBinder binder, out object result)
|
||||
{
|
||||
return godot_icall_DynamicGodotObject_GetMember(Object.GetPtr(Value), binder.Name, out result);
|
||||
}
|
||||
|
||||
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
|
||||
{
|
||||
return godot_icall_DynamicGodotObject_InvokeMember(Object.GetPtr(Value), binder.Name, args, out result);
|
||||
}
|
||||
|
||||
public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
|
||||
{
|
||||
if (indexes.Length == 1)
|
||||
{
|
||||
if (indexes[0] is string name)
|
||||
{
|
||||
return godot_icall_DynamicGodotObject_SetMember(Object.GetPtr(Value), name, value);
|
||||
}
|
||||
}
|
||||
|
||||
return base.TrySetIndex(binder, indexes, value);
|
||||
}
|
||||
|
||||
public override bool TrySetMember(SetMemberBinder binder, object value)
|
||||
{
|
||||
return godot_icall_DynamicGodotObject_SetMember(Object.GetPtr(Value), binder.Name, value);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static string[] godot_icall_DynamicGodotObject_SetMemberList(IntPtr godotObject);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static bool godot_icall_DynamicGodotObject_InvokeMember(IntPtr godotObject, string name, object[] args, out object result);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static bool godot_icall_DynamicGodotObject_GetMember(IntPtr godotObject, string name, out object result);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static bool godot_icall_DynamicGodotObject_SetMember(IntPtr godotObject, string name, object value);
|
||||
|
||||
#region We don't override these methods
|
||||
|
||||
// Looks like this is not usable from C#
|
||||
//public override bool TryCreateInstance(CreateInstanceBinder binder, object[] args, out object result);
|
||||
|
||||
// Object members cannot be deleted
|
||||
//public override bool TryDeleteIndex(DeleteIndexBinder binder, object[] indexes);
|
||||
//public override bool TryDeleteMember(DeleteMemberBinder binder);
|
||||
|
||||
// Invocation on the object itself, e.g.: obj(param)
|
||||
//public override bool TryInvoke(InvokeBinder binder, object[] args, out object result);
|
||||
|
||||
// No unnary operations to handle
|
||||
//public override bool TryUnaryOperation(UnaryOperationBinder binder, out object result);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
namespace Godot
|
||||
{
|
||||
|
@ -12,10 +12,20 @@ namespace Godot
|
|||
|
||||
public static WeakRef WeakRef(Object obj)
|
||||
{
|
||||
return godot_icall_Object_weakref(Object.GetPtr(obj));
|
||||
if (!IsInstanceValid(obj))
|
||||
return null;
|
||||
|
||||
using godot_ref weakRef = default;
|
||||
|
||||
unsafe
|
||||
{
|
||||
NativeFuncs.godotsharp_weakref(GetPtr(obj), &weakRef);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static WeakRef godot_icall_Object_weakref(IntPtr obj);
|
||||
if (weakRef.IsNull)
|
||||
return null;
|
||||
|
||||
return (WeakRef)InteropUtils.UnmanagedGetManaged(weakRef._reference);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,64 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Godot.Collections;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
namespace Godot
|
||||
{
|
||||
public partial class SceneTree
|
||||
{
|
||||
public Array<T> GetNodesInGroup<T>(StringName group) where T : class
|
||||
public unsafe 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)));
|
||||
var array = GetNodesInGroup(group);
|
||||
|
||||
if (array.Count == 0)
|
||||
return new Array<T>(array);
|
||||
|
||||
var typeOfT = typeof(T);
|
||||
bool nativeBase = InternalIsClassNativeBase(typeOfT);
|
||||
|
||||
if (nativeBase)
|
||||
{
|
||||
// Native type
|
||||
var field = typeOfT.GetField("NativeName",
|
||||
BindingFlags.DeclaredOnly | BindingFlags.Static |
|
||||
BindingFlags.Public | BindingFlags.NonPublic);
|
||||
|
||||
var nativeName = (StringName)field!.GetValue(null);
|
||||
godot_string_name nativeNameAux = nativeName.NativeValue;
|
||||
godot_array inputAux = array.NativeValue;
|
||||
godot_array filteredArray;
|
||||
NativeFuncs.godotsharp_array_filter_godot_objects_by_native(
|
||||
&nativeNameAux, &inputAux, &filteredArray);
|
||||
return Array<T>.CreateTakingOwnershipOfDisposableValue(filteredArray);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Custom derived type
|
||||
godot_array inputAux = array.NativeValue;
|
||||
godot_array filteredArray;
|
||||
NativeFuncs.godotsharp_array_filter_godot_objects_by_non_native(&inputAux, &filteredArray);
|
||||
|
||||
var filteredArrayWrapped = Array.CreateTakingOwnershipOfDisposableValue(filteredArray);
|
||||
|
||||
// Re-use first array as its size is the same or greater than the filtered one
|
||||
var resWrapped = new Array<T>(array);
|
||||
|
||||
int j = 0;
|
||||
for (int i = 0; i < filteredArrayWrapped.Count; i++)
|
||||
{
|
||||
if (filteredArrayWrapped[i] is T t)
|
||||
{
|
||||
resWrapped[j] = t;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static IntPtr godot_icall_SceneTree_get_nodes_in_group_Generic(IntPtr obj, IntPtr group, Type elemType);
|
||||
// Remove trailing elements, since this was re-used
|
||||
resWrapped.Resize(j);
|
||||
|
||||
return resWrapped;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ using real_t = System.Single;
|
|||
#endif
|
||||
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,14 +13,20 @@ 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);
|
||||
using godot_variant ret = default;
|
||||
NativeFuncs.godotsharp_bytes2var(&varBytes, allowObjects.ToGodotBool(), &ret);
|
||||
return Marshaling.variant_to_mono_object(&ret);
|
||||
}
|
||||
|
||||
public static object Convert(object what, Variant.Type type)
|
||||
public static unsafe object Convert(object what, Variant.Type type)
|
||||
{
|
||||
return godot_icall_GD_convert(what, type);
|
||||
using var whatVariant = Marshaling.mono_object_to_variant(what);
|
||||
using godot_variant ret = default;
|
||||
NativeFuncs.godotsharp_convert(&whatVariant, type, &ret);
|
||||
return Marshaling.variant_to_mono_object(&ret);
|
||||
}
|
||||
|
||||
public static real_t Db2Linear(real_t db)
|
||||
|
@ -28,7 +34,7 @@ namespace Godot
|
|||
return (real_t)Math.Exp(db * 0.11512925464970228420089957273422);
|
||||
}
|
||||
|
||||
private static object[] GetPrintParams(object[] parameters)
|
||||
private static string[] GetPrintParams(object[] parameters)
|
||||
{
|
||||
if (parameters == null)
|
||||
{
|
||||
|
@ -38,14 +44,15 @@ namespace Godot
|
|||
return Array.ConvertAll(parameters, x => x?.ToString() ?? "null");
|
||||
}
|
||||
|
||||
public static int Hash(object var)
|
||||
public static unsafe int Hash(object var)
|
||||
{
|
||||
return godot_icall_GD_hash(var);
|
||||
using var variant = Marshaling.mono_object_to_variant(var);
|
||||
return NativeFuncs.godotsharp_hash(&variant);
|
||||
}
|
||||
|
||||
public static Object InstanceFromId(ulong instanceId)
|
||||
{
|
||||
return godot_icall_GD_instance_from_id(instanceId);
|
||||
return InteropUtils.UnmanagedGetManaged(NativeFuncs.godotsharp_instance_from_id(instanceId));
|
||||
}
|
||||
|
||||
public static real_t Linear2Db(real_t linear)
|
||||
|
@ -63,19 +70,23 @@ namespace Godot
|
|||
return ResourceLoader.Load<T>(path);
|
||||
}
|
||||
|
||||
public static void PushError(string message)
|
||||
public static unsafe void PushError(string message)
|
||||
{
|
||||
godot_icall_GD_pusherror(message);
|
||||
using var godotStr = Marshaling.mono_string_to_godot(message);
|
||||
NativeFuncs.godotsharp_pusherror(&godotStr);
|
||||
}
|
||||
|
||||
public static void PushWarning(string message)
|
||||
public static unsafe void PushWarning(string message)
|
||||
{
|
||||
godot_icall_GD_pushwarning(message);
|
||||
using var godotStr = Marshaling.mono_string_to_godot(message);
|
||||
NativeFuncs.godotsharp_pushwarning(&godotStr);
|
||||
}
|
||||
|
||||
public static void Print(params object[] what)
|
||||
public static unsafe void Print(params object[] what)
|
||||
{
|
||||
godot_icall_GD_print(GetPrintParams(what));
|
||||
string str = string.Concat(GetPrintParams(what));
|
||||
using var godotStr = Marshaling.mono_string_to_godot(str);
|
||||
NativeFuncs.godotsharp_print(&godotStr);
|
||||
}
|
||||
|
||||
public static void PrintStack()
|
||||
|
@ -83,54 +94,62 @@ namespace Godot
|
|||
Print(System.Environment.StackTrace);
|
||||
}
|
||||
|
||||
public static void PrintErr(params object[] what)
|
||||
public static unsafe void PrintErr(params object[] what)
|
||||
{
|
||||
godot_icall_GD_printerr(GetPrintParams(what));
|
||||
string str = string.Concat(GetPrintParams(what));
|
||||
using var godotStr = Marshaling.mono_string_to_godot(str);
|
||||
NativeFuncs.godotsharp_printerr(&godotStr);
|
||||
}
|
||||
|
||||
public static void PrintRaw(params object[] what)
|
||||
public static unsafe void PrintRaw(params object[] what)
|
||||
{
|
||||
godot_icall_GD_printraw(GetPrintParams(what));
|
||||
string str = string.Concat(GetPrintParams(what));
|
||||
using var godotStr = Marshaling.mono_string_to_godot(str);
|
||||
NativeFuncs.godotsharp_printraw(&godotStr);
|
||||
}
|
||||
|
||||
public static void PrintS(params object[] what)
|
||||
public static unsafe void PrintS(params object[] what)
|
||||
{
|
||||
godot_icall_GD_prints(GetPrintParams(what));
|
||||
string str = string.Join(' ', GetPrintParams(what));
|
||||
using var godotStr = Marshaling.mono_string_to_godot(str);
|
||||
NativeFuncs.godotsharp_prints(&godotStr);
|
||||
}
|
||||
|
||||
public static void PrintT(params object[] what)
|
||||
public static unsafe void PrintT(params object[] what)
|
||||
{
|
||||
godot_icall_GD_printt(GetPrintParams(what));
|
||||
string str = string.Join('\t', GetPrintParams(what));
|
||||
using var godotStr = Marshaling.mono_string_to_godot(str);
|
||||
NativeFuncs.godotsharp_printt(&godotStr);
|
||||
}
|
||||
|
||||
public static float Randf()
|
||||
{
|
||||
return godot_icall_GD_randf();
|
||||
return NativeFuncs.godotsharp_randf();
|
||||
}
|
||||
|
||||
public static uint Randi()
|
||||
{
|
||||
return godot_icall_GD_randi();
|
||||
return NativeFuncs.godotsharp_randi();
|
||||
}
|
||||
|
||||
public static void Randomize()
|
||||
{
|
||||
godot_icall_GD_randomize();
|
||||
NativeFuncs.godotsharp_randomize();
|
||||
}
|
||||
|
||||
public static double RandRange(double from, double to)
|
||||
{
|
||||
return godot_icall_GD_randf_range(from, to);
|
||||
return NativeFuncs.godotsharp_randf_range(from, to);
|
||||
}
|
||||
|
||||
public static int RandRange(int from, int to)
|
||||
{
|
||||
return godot_icall_GD_randi_range(from, to);
|
||||
return NativeFuncs.godotsharp_randi_range(from, to);
|
||||
}
|
||||
|
||||
public static uint RandFromSeed(ref ulong seed)
|
||||
{
|
||||
return godot_icall_GD_rand_seed(seed, out seed);
|
||||
return NativeFuncs.godotsharp_rand_from_seed(seed, out seed);
|
||||
}
|
||||
|
||||
public static IEnumerable<int> Range(int end)
|
||||
|
@ -165,109 +184,45 @@ namespace Godot
|
|||
|
||||
public static void Seed(ulong seed)
|
||||
{
|
||||
godot_icall_GD_seed(seed);
|
||||
NativeFuncs.godotsharp_seed(seed);
|
||||
}
|
||||
|
||||
public static string Str(params object[] what)
|
||||
public static unsafe string Str(params object[] what)
|
||||
{
|
||||
return godot_icall_GD_str(what);
|
||||
using var whatGodotArray = Marshaling.mono_array_to_Array(what);
|
||||
using godot_string ret = default;
|
||||
NativeFuncs.godotsharp_str(&whatGodotArray, &ret);
|
||||
return Marshaling.mono_string_from_godot(ret);
|
||||
}
|
||||
|
||||
public static object Str2Var(string str)
|
||||
public static unsafe object Str2Var(string str)
|
||||
{
|
||||
return godot_icall_GD_str2var(str);
|
||||
using var godotStr = Marshaling.mono_string_to_godot(str);
|
||||
using godot_variant ret = default;
|
||||
NativeFuncs.godotsharp_str2var(&godotStr, &ret);
|
||||
return Marshaling.variant_to_mono_object(&ret);
|
||||
}
|
||||
|
||||
public static bool TypeExists(StringName type)
|
||||
public static unsafe byte[] Var2Bytes(object var, bool fullObjects = false)
|
||||
{
|
||||
return godot_icall_GD_type_exists(StringName.GetPtr(type));
|
||||
using var variant = Marshaling.mono_object_to_variant(var);
|
||||
using godot_packed_byte_array varBytes = default;
|
||||
NativeFuncs.godotsharp_var2bytes(&variant, fullObjects.ToGodotBool(), &varBytes);
|
||||
using (varBytes)
|
||||
return Marshaling.PackedByteArray_to_mono_array(&varBytes);
|
||||
}
|
||||
|
||||
public static byte[] Var2Bytes(object var, bool fullObjects = false)
|
||||
public static unsafe string Var2Str(object var)
|
||||
{
|
||||
return godot_icall_GD_var2bytes(var, fullObjects);
|
||||
}
|
||||
|
||||
public static string Var2Str(object var)
|
||||
{
|
||||
return godot_icall_GD_var2str(var);
|
||||
using var variant = Marshaling.mono_object_to_variant(var);
|
||||
using godot_string ret = default;
|
||||
NativeFuncs.godotsharp_var2str(&variant, &ret);
|
||||
return Marshaling.mono_string_from_godot(ret);
|
||||
}
|
||||
|
||||
public static Variant.Type TypeToVariantType(Type type)
|
||||
{
|
||||
return godot_icall_TypeToVariantType(type);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static object godot_icall_GD_bytes2var(byte[] bytes, bool allowObjects);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static object godot_icall_GD_convert(object what, Variant.Type type);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static int godot_icall_GD_hash(object var);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static Object godot_icall_GD_instance_from_id(ulong instanceId);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_GD_print(object[] what);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_GD_printerr(object[] what);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_GD_printraw(object[] what);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_GD_prints(object[] what);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_GD_printt(object[] what);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static float godot_icall_GD_randf();
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static uint godot_icall_GD_randi();
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_GD_randomize();
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static 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);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static uint godot_icall_GD_rand_seed(ulong seed, out ulong newSeed);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_GD_seed(ulong seed);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static string godot_icall_GD_str(object[] what);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static object godot_icall_GD_str2var(string str);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static bool godot_icall_GD_type_exists(IntPtr type);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static byte[] godot_icall_GD_var2bytes(object what, bool fullObjects);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static string godot_icall_GD_var2str(object var);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_GD_pusherror(string type);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static void godot_icall_GD_pushwarning(string type);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern Variant.Type godot_icall_TypeToVariantType(Type type);
|
||||
return Marshaling.managed_to_variant_type(type, out bool _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,10 +17,7 @@ namespace Godot
|
|||
public override void Fail(string message, string detailMessage)
|
||||
{
|
||||
GD.PrintErr("Assertion failed: ", message);
|
||||
if (detailMessage != null)
|
||||
{
|
||||
GD.PrintErr(" Details: ", detailMessage);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
|
|
|
@ -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,74 @@
|
|||
using System;
|
||||
|
||||
namespace Godot.NativeInterop
|
||||
{
|
||||
internal static class ExceptionUtils
|
||||
{
|
||||
public static void PushError(string message)
|
||||
{
|
||||
GD.PushError(message);
|
||||
}
|
||||
|
||||
private static void OnExceptionLoggerException(Exception loggerException, Exception exceptionToLog)
|
||||
{
|
||||
// This better not throw
|
||||
PushError("Exception thrown when trying to log another exception...");
|
||||
PushError("Exception:");
|
||||
PushError(exceptionToLog.ToString());
|
||||
PushError("Logger exception:");
|
||||
PushError(loggerException.ToString());
|
||||
}
|
||||
|
||||
public static void DebugPrintUnhandledException(Exception e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// TODO Not implemented (debug_print_unhandled_exception)
|
||||
GD.PushError(e.ToString());
|
||||
}
|
||||
catch (Exception unexpected)
|
||||
{
|
||||
OnExceptionLoggerException(unexpected, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DebugSendUnhandledExceptionError(Exception e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// TODO Not implemented (debug_send_unhandled_exception_error)
|
||||
GD.PushError(e.ToString());
|
||||
}
|
||||
catch (Exception unexpected)
|
||||
{
|
||||
OnExceptionLoggerException(unexpected, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void DebugUnhandledException(Exception e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// TODO Not implemented (debug_unhandled_exception)
|
||||
GD.PushError(e.ToString());
|
||||
}
|
||||
catch (Exception unexpected)
|
||||
{
|
||||
OnExceptionLoggerException(unexpected, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void PrintUnhandledException(Exception e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// TODO Not implemented (print_unhandled_exception)
|
||||
GD.PushError(e.ToString());
|
||||
}
|
||||
catch (Exception unexpected)
|
||||
{
|
||||
OnExceptionLoggerException(unexpected, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,481 @@
|
|||
#if REAL_T_IS_DOUBLE
|
||||
using real_t = System.Double;
|
||||
#else
|
||||
using real_t = System.Single;
|
||||
#endif
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Godot.NativeInterop
|
||||
{
|
||||
internal static class GodotBoolExtensions
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static unsafe godot_bool ToGodotBool(this bool @bool)
|
||||
{
|
||||
return *(godot_bool*)&@bool;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static unsafe bool ToBool(this godot_bool godotBool)
|
||||
{
|
||||
return *(bool*)&godotBool;
|
||||
}
|
||||
}
|
||||
|
||||
// Apparently a struct with a byte is not blittable? It crashes when calling a UnmanagedCallersOnly function ptr.
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public enum godot_bool : byte
|
||||
{
|
||||
True = 1,
|
||||
False = 0
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public struct godot_ref : IDisposable
|
||||
{
|
||||
internal IntPtr _reference;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_reference == IntPtr.Zero)
|
||||
return;
|
||||
NativeFuncs.godotsharp_ref_destroy(ref this);
|
||||
_reference = IntPtr.Zero;
|
||||
}
|
||||
|
||||
public bool IsNull => _reference == IntPtr.Zero;
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
public 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
|
||||
public struct godot_variant_call_error
|
||||
{
|
||||
public godot_variant_call_error_error error;
|
||||
public int argument;
|
||||
public Godot.Variant.Type expected;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public 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
|
||||
public struct godot_string : IDisposable
|
||||
{
|
||||
internal IntPtr _ptr;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_ptr == IntPtr.Zero)
|
||||
return;
|
||||
NativeFuncs.godotsharp_string_destroy(ref this);
|
||||
_ptr = IntPtr.Zero;
|
||||
}
|
||||
|
||||
// Size including the null termination character
|
||||
public unsafe int Size => _ptr != IntPtr.Zero ? *((int*)_ptr - 1) : 0;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public 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
|
||||
public 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
|
||||
public 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
|
||||
public 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
|
||||
public struct godot_array : IDisposable
|
||||
{
|
||||
internal unsafe ArrayPrivate* _p;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct ArrayPrivate
|
||||
{
|
||||
private uint _safeRefCount;
|
||||
|
||||
internal VariantVector _arrayVector;
|
||||
// There's more here, but we don't care as we never store this in C#
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct VariantVector
|
||||
{
|
||||
internal IntPtr _writeProxy;
|
||||
internal unsafe godot_variant* _ptr;
|
||||
|
||||
public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
|
||||
}
|
||||
|
||||
public unsafe int Size => _p != null ? _p->_arrayVector.Size : 0;
|
||||
|
||||
public unsafe void Dispose()
|
||||
{
|
||||
if (_p == null)
|
||||
return;
|
||||
NativeFuncs.godotsharp_array_destroy(ref this);
|
||||
_p = null;
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
public 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
|
||||
public struct godot_packed_byte_array : IDisposable
|
||||
{
|
||||
internal IntPtr _writeProxy;
|
||||
internal unsafe byte* _ptr;
|
||||
|
||||
public unsafe void Dispose()
|
||||
{
|
||||
if (_ptr == null)
|
||||
return;
|
||||
NativeFuncs.godotsharp_packed_byte_array_destroy(ref this);
|
||||
_ptr = null;
|
||||
}
|
||||
|
||||
public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public struct godot_packed_int32_array : IDisposable
|
||||
{
|
||||
internal IntPtr _writeProxy;
|
||||
internal unsafe int* _ptr;
|
||||
|
||||
public unsafe void Dispose()
|
||||
{
|
||||
if (_ptr == null)
|
||||
return;
|
||||
NativeFuncs.godotsharp_packed_int32_array_destroy(ref this);
|
||||
_ptr = null;
|
||||
}
|
||||
|
||||
public unsafe int Size => _ptr != null ? *(_ptr - 1) : 0;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public struct godot_packed_int64_array : IDisposable
|
||||
{
|
||||
internal IntPtr _writeProxy;
|
||||
internal unsafe long* _ptr;
|
||||
|
||||
public unsafe void Dispose()
|
||||
{
|
||||
if (_ptr == null)
|
||||
return;
|
||||
NativeFuncs.godotsharp_packed_int64_array_destroy(ref this);
|
||||
_ptr = null;
|
||||
}
|
||||
|
||||
public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public struct godot_packed_float32_array : IDisposable
|
||||
{
|
||||
internal IntPtr _writeProxy;
|
||||
internal unsafe float* _ptr;
|
||||
|
||||
public unsafe void Dispose()
|
||||
{
|
||||
if (_ptr == null)
|
||||
return;
|
||||
NativeFuncs.godotsharp_packed_float32_array_destroy(ref this);
|
||||
_ptr = null;
|
||||
}
|
||||
|
||||
public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public struct godot_packed_float64_array : IDisposable
|
||||
{
|
||||
internal IntPtr _writeProxy;
|
||||
internal unsafe double* _ptr;
|
||||
|
||||
public unsafe void Dispose()
|
||||
{
|
||||
if (_ptr == null)
|
||||
return;
|
||||
NativeFuncs.godotsharp_packed_float64_array_destroy(ref this);
|
||||
_ptr = null;
|
||||
}
|
||||
|
||||
public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public struct godot_packed_string_array : IDisposable
|
||||
{
|
||||
internal IntPtr _writeProxy;
|
||||
internal unsafe godot_string* _ptr;
|
||||
|
||||
public unsafe void Dispose()
|
||||
{
|
||||
if (_ptr == null)
|
||||
return;
|
||||
NativeFuncs.godotsharp_packed_string_array_destroy(ref this);
|
||||
_ptr = null;
|
||||
}
|
||||
|
||||
public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public struct godot_packed_vector2_array : IDisposable
|
||||
{
|
||||
internal IntPtr _writeProxy;
|
||||
internal unsafe Vector2* _ptr;
|
||||
|
||||
public unsafe void Dispose()
|
||||
{
|
||||
if (_ptr == null)
|
||||
return;
|
||||
NativeFuncs.godotsharp_packed_vector2_array_destroy(ref this);
|
||||
_ptr = null;
|
||||
}
|
||||
|
||||
public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public struct godot_packed_vector3_array : IDisposable
|
||||
{
|
||||
internal IntPtr _writeProxy;
|
||||
internal unsafe Vector3* _ptr;
|
||||
|
||||
public unsafe void Dispose()
|
||||
{
|
||||
if (_ptr == null)
|
||||
return;
|
||||
NativeFuncs.godotsharp_packed_vector3_array_destroy(ref this);
|
||||
_ptr = null;
|
||||
}
|
||||
|
||||
public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public struct godot_packed_color_array : IDisposable
|
||||
{
|
||||
internal IntPtr _writeProxy;
|
||||
internal unsafe Color* _ptr;
|
||||
|
||||
public unsafe void Dispose()
|
||||
{
|
||||
if (_ptr == null)
|
||||
return;
|
||||
NativeFuncs.godotsharp_packed_color_array_destroy(ref this);
|
||||
_ptr = null;
|
||||
}
|
||||
|
||||
public unsafe int Size => _ptr != null ? *((int*)_ptr - 1) : 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Godot.Bridge;
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace Godot.NativeInterop
|
||||
{
|
||||
internal static class InteropUtils
|
||||
{
|
||||
public static Object UnmanagedGetManaged(IntPtr unmanaged)
|
||||
{
|
||||
// The native pointer may be null
|
||||
if (unmanaged == IntPtr.Zero)
|
||||
return null;
|
||||
|
||||
IntPtr gcHandlePtr;
|
||||
godot_bool has_cs_script_instance = false.ToGodotBool();
|
||||
|
||||
// First try to get the tied managed instance from a CSharpInstance script instance
|
||||
|
||||
unsafe
|
||||
{
|
||||
gcHandlePtr = NativeFuncs.godotsharp_internal_unmanaged_get_script_instance_managed(
|
||||
unmanaged, &has_cs_script_instance);
|
||||
}
|
||||
|
||||
if (gcHandlePtr != IntPtr.Zero)
|
||||
return (Object)GCHandle.FromIntPtr(gcHandlePtr).Target;
|
||||
|
||||
// Otherwise, if the object has a CSharpInstance script instance, return null
|
||||
|
||||
if (has_cs_script_instance.ToBool())
|
||||
return null;
|
||||
|
||||
// If it doesn't have a CSharpInstance script instance, try with native instance bindings
|
||||
|
||||
gcHandlePtr = NativeFuncs.godotsharp_internal_unmanaged_get_instance_binding_managed(unmanaged);
|
||||
|
||||
object target = gcHandlePtr != IntPtr.Zero ? GCHandle.FromIntPtr(gcHandlePtr).Target : null;
|
||||
|
||||
if (target != null)
|
||||
return (Object)target;
|
||||
|
||||
// If the native instance binding GC handle target was collected, create a new one
|
||||
|
||||
gcHandlePtr = NativeFuncs.godotsharp_internal_unmanaged_instance_binding_create_managed(
|
||||
unmanaged, gcHandlePtr);
|
||||
|
||||
return gcHandlePtr != IntPtr.Zero ? (Object)GCHandle.FromIntPtr(gcHandlePtr).Target : null;
|
||||
}
|
||||
|
||||
public static void TieManagedToUnmanaged(Object managed, IntPtr unmanaged,
|
||||
StringName nativeName, bool refCounted, Type type, Type nativeType)
|
||||
{
|
||||
var gcHandle = GCHandle.Alloc(managed, refCounted ? GCHandleType.Weak : GCHandleType.Normal);
|
||||
|
||||
if (type == nativeType)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
godot_string_name nativeNameAux = nativeName.NativeValue;
|
||||
NativeFuncs.godotsharp_internal_tie_native_managed_to_unmanaged(
|
||||
GCHandle.ToIntPtr(gcHandle), unmanaged, &nativeNameAux, refCounted.ToGodotBool());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IntPtr scriptPtr = NativeFuncs.godotsharp_internal_new_csharp_script();
|
||||
|
||||
ScriptManagerBridge.AddScriptBridgeWithType(scriptPtr, type);
|
||||
|
||||
// IMPORTANT: This must be called after AddScriptWithTypeBridge
|
||||
NativeFuncs.godotsharp_internal_tie_user_managed_to_unmanaged(
|
||||
GCHandle.ToIntPtr(gcHandle), unmanaged, scriptPtr, refCounted.ToGodotBool());
|
||||
}
|
||||
}
|
||||
|
||||
public static void TieManagedToUnmanagedWithPreSetup(Object managed, IntPtr unmanaged)
|
||||
{
|
||||
var strongGCHandle = GCHandle.Alloc(managed, GCHandleType.Normal);
|
||||
NativeFuncs.godotsharp_internal_tie_managed_to_unmanaged_with_pre_setup(
|
||||
GCHandle.ToIntPtr(strongGCHandle), 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,608 @@
|
|||
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
|
||||
public 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);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern delegate* unmanaged<IntPtr> godotsharp_get_class_constructor(
|
||||
ref godot_string_name p_classname);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern IntPtr godotsharp_engine_get_singleton(godot_string* p_name);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
internal static extern void godotsharp_internal_object_disposed(IntPtr ptr);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
internal static extern void godotsharp_internal_refcounted_disposed(IntPtr ptr, godot_bool isFinalizer);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
internal static extern void godotsharp_internal_object_connect_event_signal(IntPtr obj,
|
||||
godot_string_name* eventSignal);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
internal static extern Error godotsharp_internal_signal_awaiter_connect(IntPtr source,
|
||||
ref godot_string_name signal,
|
||||
IntPtr target, IntPtr awaiterHandlePtr);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_internal_tie_native_managed_to_unmanaged(IntPtr gcHandleIntPtr,
|
||||
IntPtr unmanaged, godot_string_name* nativeName, godot_bool refCounted);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_internal_tie_user_managed_to_unmanaged(IntPtr gcHandleIntPtr,
|
||||
IntPtr unmanaged, IntPtr scriptPtr, godot_bool refCounted);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_internal_tie_managed_to_unmanaged_with_pre_setup(
|
||||
IntPtr gcHandleIntPtr, IntPtr unmanaged);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern IntPtr godotsharp_internal_unmanaged_get_script_instance_managed(IntPtr p_unmanaged,
|
||||
godot_bool* r_has_cs_script_instance);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern IntPtr godotsharp_internal_unmanaged_get_instance_binding_managed(IntPtr p_unmanaged);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern IntPtr godotsharp_internal_unmanaged_instance_binding_create_managed(IntPtr p_unmanaged,
|
||||
IntPtr oldGCHandlePtr);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern IntPtr godotsharp_internal_new_csharp_script();
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_array_filter_godot_objects_by_native(godot_string_name* p_native_name,
|
||||
godot_array* p_input, godot_array* r_output);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_array_filter_godot_objects_by_non_native(godot_array* p_input,
|
||||
godot_array* r_output);
|
||||
|
||||
[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 godot_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 godot_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);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_bool godotsharp_variant_equals(godot_variant* p_a, godot_variant* p_b);
|
||||
|
||||
// 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(godot_array* p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_array_new_copy(godot_array* r_dest, godot_array* p_src);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_variant* godotsharp_array_ptrw(ref godot_array p_self);
|
||||
|
||||
// dictionary.h
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_dictionary_new(godot_dictionary* p_self);
|
||||
|
||||
[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);
|
||||
|
||||
// Array
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern int godotsharp_array_add(ref godot_array p_self, godot_variant* p_item);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void
|
||||
godotsharp_array_duplicate(ref godot_array p_self, godot_bool p_deep, out godot_array r_dest);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern int godotsharp_array_index_of(ref godot_array p_self, godot_variant* p_item);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_array_insert(ref godot_array p_self, int p_index, godot_variant* p_item);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_array_remove_at(ref godot_array p_self, int p_index);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern Error godotsharp_array_resize(ref godot_array p_self, int p_new_size);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern Error godotsharp_array_shuffle(ref godot_array p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_array_to_string(ref godot_array p_self, godot_string* r_str);
|
||||
|
||||
// Dictionary
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_bool godotsharp_dictionary_try_get_value(ref godot_dictionary p_self,
|
||||
godot_variant* p_key,
|
||||
out godot_variant r_value);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_dictionary_set_value(ref godot_dictionary p_self, godot_variant* p_key,
|
||||
godot_variant* p_value);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_dictionary_keys(ref godot_dictionary p_self, out godot_array r_dest);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_dictionary_values(ref godot_dictionary p_self, out godot_array r_dest);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern int godotsharp_dictionary_count(ref godot_dictionary p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_dictionary_key_value_pair_at(ref godot_dictionary p_self, int p_index,
|
||||
out godot_variant r_key, out godot_variant r_value);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_dictionary_add(ref godot_dictionary p_self, godot_variant* p_key,
|
||||
godot_variant* p_value);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_dictionary_clear(ref godot_dictionary p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_bool godotsharp_dictionary_contains_key(ref godot_dictionary p_self,
|
||||
godot_variant* p_key);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_dictionary_duplicate(ref godot_dictionary p_self, godot_bool p_deep,
|
||||
out godot_dictionary r_dest);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_bool godotsharp_dictionary_remove_key(ref godot_dictionary p_self,
|
||||
godot_variant* p_key);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_dictionary_to_string(ref godot_dictionary p_self, godot_string* r_str);
|
||||
|
||||
// StringExtensions
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_string_md5_buffer(godot_string* p_self,
|
||||
godot_packed_byte_array* r_md5_buffer);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_string_md5_text(godot_string* p_self, godot_string* r_md5_text);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern int godotsharp_string_rfind(godot_string* p_self, godot_string* p_what, int p_from);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern int godotsharp_string_rfindn(godot_string* p_self, godot_string* p_what, int p_from);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_string_sha256_buffer(godot_string* p_self,
|
||||
godot_packed_byte_array* r_sha256_buffer);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_string_sha256_text(godot_string* p_self, godot_string* r_sha256_text);
|
||||
|
||||
// NodePath
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_node_path_get_as_property_path(ref godot_node_path p_self,
|
||||
ref godot_node_path r_dest);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_node_path_get_concatenated_subnames(ref godot_node_path p_self,
|
||||
godot_string* r_subnames);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_node_path_get_name(ref godot_node_path p_self, int p_idx,
|
||||
godot_string* r_name);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern int godotsharp_node_path_get_name_count(ref godot_node_path p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_node_path_get_subname(ref godot_node_path p_self, int p_idx,
|
||||
godot_string* r_subname);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern int godotsharp_node_path_get_subname_count(ref godot_node_path p_self);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern godot_bool godotsharp_node_path_is_absolute(ref godot_node_path p_self);
|
||||
|
||||
// GD, etc
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_bytes2var(godot_packed_byte_array* p_bytes, godot_bool p_allow_objects,
|
||||
godot_variant* r_ret);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_convert(godot_variant* p_what, Variant.Type p_type, godot_variant* r_ret);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern int godotsharp_hash(godot_variant* var);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern IntPtr godotsharp_instance_from_id(ulong instanceId);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_print(godot_string* p_what);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_printerr(godot_string* p_what);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_printraw(godot_string* p_what);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_prints(godot_string* p_what);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_printt(godot_string* p_what);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern float godotsharp_randf();
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern uint godotsharp_randi();
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_randomize();
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern double godotsharp_randf_range(double from, double to);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern int godotsharp_randi_range(int from, int to);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern uint godotsharp_rand_from_seed(ulong seed, out ulong newSeed);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_seed(ulong seed);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_weakref(IntPtr obj, godot_ref* r_weak_ref);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern string godotsharp_str(godot_array* p_what, godot_string* r_ret);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_str2var(godot_string* p_str, godot_variant* r_ret);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_var2bytes(godot_variant* what, godot_bool fullObjects,
|
||||
godot_packed_byte_array* bytes);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_var2str(godot_variant* var, godot_string* r_ret);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_pusherror(godot_string* type);
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern void godotsharp_pushwarning(godot_string* type);
|
||||
|
||||
// Object
|
||||
|
||||
[DllImport(GodotDllName)]
|
||||
public static extern string godotsharp_object_to_string(IntPtr ptr, godot_string* r_str);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace Godot.NativeInterop
|
||||
{
|
||||
public 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()
|
||||
{
|
||||
godot_array ret;
|
||||
godotsharp_array_new(&ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
godot_dictionary ret;
|
||||
godotsharp_dictionary_new(&ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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,355 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
namespace Godot.NativeInterop
|
||||
{
|
||||
public 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.ToGodotBool() } };
|
||||
|
||||
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.ToBool() :
|
||||
NativeFuncs.godotsharp_variant_as_bool(p_var).ToBool();
|
||||
|
||||
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;
|
||||
}
|
||||
public godot_node_path NativeValue;
|
||||
|
||||
~NodePath()
|
||||
{
|
||||
|
@ -31,112 +19,90 @@ 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;
|
||||
// Always dispose `NativeValue` even if disposing is true
|
||||
NativeValue.Dispose();
|
||||
}
|
||||
|
||||
disposed = true;
|
||||
}
|
||||
|
||||
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;
|
||||
NativeFuncs.godotsharp_node_path_get_as_property_path(ref NativeValue, ref propertyPath);
|
||||
return CreateTakingOwnershipOfDisposableValue(propertyPath);
|
||||
}
|
||||
|
||||
public string GetConcatenatedSubnames()
|
||||
public unsafe string GetConcatenatedSubNames()
|
||||
{
|
||||
return godot_icall_NodePath_get_concatenated_subnames(GetPtr(this));
|
||||
using godot_string subNames = default;
|
||||
NativeFuncs.godotsharp_node_path_get_concatenated_subnames(ref NativeValue, &subNames);
|
||||
return Marshaling.mono_string_from_godot(subNames);
|
||||
}
|
||||
|
||||
public string GetName(int idx)
|
||||
public unsafe string GetName(int idx)
|
||||
{
|
||||
return godot_icall_NodePath_get_name(GetPtr(this), idx);
|
||||
using godot_string name = default;
|
||||
NativeFuncs.godotsharp_node_path_get_name(ref NativeValue, idx, &name);
|
||||
return Marshaling.mono_string_from_godot(name);
|
||||
}
|
||||
|
||||
public int GetNameCount()
|
||||
{
|
||||
return godot_icall_NodePath_get_name_count(GetPtr(this));
|
||||
return NativeFuncs.godotsharp_node_path_get_name_count(ref NativeValue);
|
||||
}
|
||||
|
||||
public string GetSubname(int idx)
|
||||
public unsafe string GetSubName(int idx)
|
||||
{
|
||||
return godot_icall_NodePath_get_subname(GetPtr(this), idx);
|
||||
using godot_string subName = default;
|
||||
NativeFuncs.godotsharp_node_path_get_subname(ref NativeValue, idx, &subName);
|
||||
return Marshaling.mono_string_from_godot(subName);
|
||||
}
|
||||
|
||||
public int GetSubnameCount()
|
||||
public int GetSubNameCount()
|
||||
{
|
||||
return godot_icall_NodePath_get_subname_count(GetPtr(this));
|
||||
return NativeFuncs.godotsharp_node_path_get_subname_count(ref NativeValue);
|
||||
}
|
||||
|
||||
public bool IsAbsolute()
|
||||
{
|
||||
return godot_icall_NodePath_is_absolute(GetPtr(this));
|
||||
return NativeFuncs.godotsharp_node_path_is_absolute(ref NativeValue).ToBool();
|
||||
}
|
||||
|
||||
public bool IsEmpty()
|
||||
{
|
||||
return godot_icall_NodePath_is_empty(GetPtr(this));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern IntPtr godot_icall_NodePath_Ctor(string path);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern void godot_icall_NodePath_Dtor(IntPtr ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string godot_icall_NodePath_operator_String(IntPtr ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern IntPtr godot_icall_NodePath_get_as_property_path(IntPtr ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string godot_icall_NodePath_get_concatenated_subnames(IntPtr ptr);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
private static extern string godot_icall_NodePath_get_name(IntPtr ptr, int arg1);
|
||||
|
||||
[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);
|
||||
public bool IsEmpty => godot_node_path.IsEmpty(in NativeValue);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,48 +1,80 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
namespace Godot
|
||||
{
|
||||
public partial class Object : IDisposable
|
||||
{
|
||||
private bool disposed = false;
|
||||
private bool _disposed = false;
|
||||
private Type _cachedType = typeof(Object);
|
||||
|
||||
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)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
NativePtr = NativeCtor();
|
||||
}
|
||||
|
||||
InteropUtils.TieManagedToUnmanaged(this, NativePtr,
|
||||
NativeName, refCounted: false, GetType(), _cachedType);
|
||||
}
|
||||
else
|
||||
{
|
||||
InteropUtils.TieManagedToUnmanagedWithPreSetup(this, NativePtr);
|
||||
}
|
||||
|
||||
_InitializeGodotScriptInstanceInternals();
|
||||
}
|
||||
|
||||
internal void _InitializeGodotScriptInstanceInternals()
|
||||
{
|
||||
godot_icall_Object_ConnectEventSignals(ptr);
|
||||
// Performance is not critical here as this will be replaced with source generators.
|
||||
Type top = GetType();
|
||||
Type native = InternalGetClassNativeBase(top);
|
||||
|
||||
while (top != null && top != native)
|
||||
{
|
||||
foreach (var eventSignal in top.GetEvents(
|
||||
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||
BindingFlags.NonPublic | BindingFlags.Public)
|
||||
.Where(ev => ev.GetCustomAttributes().OfType<SignalAttribute>().Any()))
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
using var eventSignalName = new StringName(eventSignal.Name);
|
||||
godot_string_name eventSignalNameAux = eventSignalName.NativeValue;
|
||||
NativeFuncs.godotsharp_internal_object_connect_event_signal(NativePtr, &eventSignalNameAux);
|
||||
}
|
||||
}
|
||||
|
||||
top = top.BaseType;
|
||||
}
|
||||
}
|
||||
|
||||
internal Object(bool memoryOwn)
|
||||
{
|
||||
this.memoryOwn = memoryOwn;
|
||||
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,30 +90,32 @@ 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;
|
||||
NativeFuncs.godotsharp_internal_refcounted_disposed(NativePtr, (!disposing).ToGodotBool());
|
||||
}
|
||||
else
|
||||
{
|
||||
godot_icall_Object_Disposed(this, ptr);
|
||||
NativeFuncs.godotsharp_internal_object_disposed(NativePtr);
|
||||
}
|
||||
|
||||
this.ptr = IntPtr.Zero;
|
||||
NativePtr = IntPtr.Zero;
|
||||
}
|
||||
|
||||
disposed = true;
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
public override unsafe string ToString()
|
||||
{
|
||||
return godot_icall_Object_ToString(GetPtr(this));
|
||||
using godot_string str = default;
|
||||
NativeFuncs.godotsharp_object_to_string(GetPtr(this), &str);
|
||||
return Marshaling.mono_string_from_godot(str);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -112,33 +146,236 @@ namespace Godot
|
|||
return new SignalAwaiter(source, signal, this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a new <see cref="Godot.DynamicGodotObject"/> associated with this instance.
|
||||
/// </summary>
|
||||
public dynamic DynamicObject => new DynamicGodotObject(this);
|
||||
|
||||
internal static IntPtr __ClassDB_get_method(StringName type, string method)
|
||||
internal static Type InternalGetClassNativeBase(Type t)
|
||||
{
|
||||
return godot_icall_Object_ClassDB_get_method(StringName.GetPtr(type), method);
|
||||
do
|
||||
{
|
||||
var assemblyName = t.Assembly.GetName();
|
||||
|
||||
if (assemblyName.Name == "GodotSharp")
|
||||
return t;
|
||||
|
||||
if (assemblyName.Name == "GodotSharpEditor")
|
||||
return t;
|
||||
} while ((t = t.BaseType) != null);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal static extern IntPtr godot_icall_Object_Ctor(Object obj);
|
||||
internal static bool InternalIsClassNativeBase(Type t)
|
||||
{
|
||||
var assemblyName = t.Assembly.GetName();
|
||||
return assemblyName.Name == "GodotSharp" || assemblyName.Name == "GodotSharpEditor";
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal static extern void godot_icall_Object_Disposed(Object obj, IntPtr ptr);
|
||||
internal unsafe bool InternalGodotScriptCallViaReflection(string method, godot_variant** args, int argCount,
|
||||
out godot_variant ret)
|
||||
{
|
||||
// Performance is not critical here as this will be replaced with source generators.
|
||||
Type top = GetType();
|
||||
Type native = InternalGetClassNativeBase(top);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal static extern void godot_icall_RefCounted_Disposed(Object obj, IntPtr ptr, bool isFinalizer);
|
||||
while (top != null && top != native)
|
||||
{
|
||||
var methodInfo = top.GetMethod(method,
|
||||
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||
BindingFlags.NonPublic | BindingFlags.Public);
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal static extern void godot_icall_Object_ConnectEventSignals(IntPtr obj);
|
||||
if (methodInfo != null)
|
||||
{
|
||||
var parameters = methodInfo.GetParameters();
|
||||
int paramCount = parameters.Length;
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal static extern string godot_icall_Object_ToString(IntPtr ptr);
|
||||
if (argCount == paramCount)
|
||||
{
|
||||
object[] invokeParams = new object[paramCount];
|
||||
|
||||
// Used by the generated API
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal static extern IntPtr godot_icall_Object_ClassDB_get_method(IntPtr type, string method);
|
||||
for (int i = 0; i < paramCount; i++)
|
||||
{
|
||||
invokeParams[i] = Marshaling.variant_to_mono_object_of_type(
|
||||
args[i], parameters[i].ParameterType);
|
||||
}
|
||||
|
||||
object retObj = methodInfo.Invoke(this, invokeParams);
|
||||
|
||||
ret = Marshaling.mono_object_to_variant(retObj);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
top = top.BaseType;
|
||||
}
|
||||
|
||||
ret = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
internal unsafe bool InternalGodotScriptSetFieldOrPropViaReflection(string name, godot_variant* value)
|
||||
{
|
||||
// Performance is not critical here as this will be replaced with source generators.
|
||||
Type top = GetType();
|
||||
Type native = InternalGetClassNativeBase(top);
|
||||
|
||||
while (top != null && top != native)
|
||||
{
|
||||
var fieldInfo = top.GetField(name,
|
||||
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||
BindingFlags.NonPublic | BindingFlags.Public);
|
||||
|
||||
if (fieldInfo != null)
|
||||
{
|
||||
object valueManaged = Marshaling.variant_to_mono_object_of_type(value, fieldInfo.FieldType);
|
||||
fieldInfo.SetValue(this, valueManaged);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
var propertyInfo = top.GetProperty(name,
|
||||
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||
BindingFlags.NonPublic | BindingFlags.Public);
|
||||
|
||||
if (propertyInfo != null)
|
||||
{
|
||||
object valueManaged = Marshaling.variant_to_mono_object_of_type(value, propertyInfo.PropertyType);
|
||||
propertyInfo.SetValue(this, valueManaged);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
top = top.BaseType;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
internal bool InternalGodotScriptGetFieldOrPropViaReflection(string name, out godot_variant value)
|
||||
{
|
||||
// Performance is not critical here as this will be replaced with source generators.
|
||||
Type top = GetType();
|
||||
Type native = InternalGetClassNativeBase(top);
|
||||
|
||||
while (top != null && top != native)
|
||||
{
|
||||
var fieldInfo = top.GetField(name,
|
||||
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||
BindingFlags.NonPublic | BindingFlags.Public);
|
||||
|
||||
if (fieldInfo != null)
|
||||
{
|
||||
object valueManaged = fieldInfo.GetValue(this);
|
||||
value = Marshaling.mono_object_to_variant(valueManaged);
|
||||
return true;
|
||||
}
|
||||
|
||||
var propertyInfo = top.GetProperty(name,
|
||||
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||
BindingFlags.NonPublic | BindingFlags.Public);
|
||||
|
||||
if (propertyInfo != null)
|
||||
{
|
||||
object valueManaged = propertyInfo.GetValue(this);
|
||||
value = Marshaling.mono_object_to_variant(valueManaged);
|
||||
return true;
|
||||
}
|
||||
|
||||
top = top.BaseType;
|
||||
}
|
||||
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
internal unsafe void InternalRaiseEventSignal(godot_string_name* eventSignalName, godot_variant** args,
|
||||
int argc)
|
||||
{
|
||||
// Performance is not critical here as this will be replaced with source generators.
|
||||
|
||||
using var stringName = StringName.CreateTakingOwnershipOfDisposableValue(
|
||||
NativeFuncs.godotsharp_string_name_new_copy(eventSignalName));
|
||||
string eventSignalNameStr = stringName.ToString();
|
||||
|
||||
Type top = GetType();
|
||||
Type native = InternalGetClassNativeBase(top);
|
||||
|
||||
while (top != null && top != native)
|
||||
{
|
||||
var foundEventSignals = top.GetEvents(
|
||||
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||
BindingFlags.NonPublic | BindingFlags.Public)
|
||||
.Where(ev => ev.GetCustomAttributes().OfType<SignalAttribute>().Any())
|
||||
.Select(ev => ev.Name);
|
||||
|
||||
var fields = top.GetFields(
|
||||
BindingFlags.DeclaredOnly | BindingFlags.Instance |
|
||||
BindingFlags.NonPublic | BindingFlags.Public);
|
||||
|
||||
var eventSignalField = fields
|
||||
.Where(f => typeof(Delegate).IsAssignableFrom(f.FieldType))
|
||||
.Where(f => foundEventSignals.Contains(f.Name))
|
||||
.FirstOrDefault(f => f.Name == eventSignalNameStr);
|
||||
|
||||
if (eventSignalField != null)
|
||||
{
|
||||
var @delegate = (Delegate)eventSignalField.GetValue(this);
|
||||
|
||||
if (@delegate == null)
|
||||
continue;
|
||||
|
||||
var delegateType = eventSignalField.FieldType;
|
||||
|
||||
var invokeMethod = delegateType.GetMethod("Invoke");
|
||||
|
||||
if (invokeMethod == null)
|
||||
throw new MissingMethodException(delegateType.FullName, "Invoke");
|
||||
|
||||
var parameterInfos = invokeMethod.GetParameters();
|
||||
var paramsLength = parameterInfos.Length;
|
||||
|
||||
if (argc != paramsLength)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"The event delegate expects {paramsLength} arguments, but received {argc}.");
|
||||
}
|
||||
|
||||
var managedArgs = new object[argc];
|
||||
|
||||
for (uint i = 0; i < argc; i++)
|
||||
{
|
||||
managedArgs[i] = Marshaling.variant_to_mono_object_of_type(
|
||||
args[i], parameterInfos[i].ParameterType);
|
||||
}
|
||||
|
||||
invokeMethod.Invoke(@delegate, managedArgs);
|
||||
return;
|
||||
}
|
||||
|
||||
top = top.BaseType;
|
||||
}
|
||||
}
|
||||
|
||||
internal static unsafe IntPtr ClassDB_get_method(StringName type, string method)
|
||||
{
|
||||
IntPtr methodBind;
|
||||
fixed (char* methodChars = method)
|
||||
{
|
||||
methodBind = NativeFuncs.godotsharp_method_bind_get_method(ref type.NativeValue, methodChars);
|
||||
}
|
||||
|
||||
if (methodBind == IntPtr.Zero)
|
||||
throw new NativeMethodBindNotFoundException(type + "." + method);
|
||||
|
||||
return methodBind;
|
||||
}
|
||||
|
||||
internal static unsafe delegate* unmanaged<IntPtr> ClassDB_get_constructor(StringName type)
|
||||
{
|
||||
// for some reason the '??' operator doesn't support 'delegate*'
|
||||
var nativeConstructor = NativeFuncs.godotsharp_get_class_constructor(ref type.NativeValue);
|
||||
|
||||
if (nativeConstructor == null)
|
||||
throw new NativeConstructorNotFoundException(type);
|
||||
|
||||
return nativeConstructor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,66 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
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);
|
||||
NativeFuncs.godotsharp_internal_signal_awaiter_connect(Object.GetPtr(source), ref signal.NativeValue,
|
||||
Object.GetPtr(target), GCHandle.ToIntPtr(GCHandle.Alloc(this)));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static Error godot_icall_SignalAwaiter_connect(IntPtr source, IntPtr 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()
|
||||
public object[] GetResult() => _result;
|
||||
|
||||
public IAwaiter<object[]> GetAwaiter() => this;
|
||||
|
||||
[UnmanagedCallersOnly]
|
||||
internal static unsafe void SignalCallback(IntPtr awaiterGCHandlePtr, godot_variant** args, int argCount,
|
||||
godot_bool* outAwaiterIsNull)
|
||||
{
|
||||
return result;
|
||||
try
|
||||
{
|
||||
var awaiter = (SignalAwaiter)GCHandle.FromIntPtr(awaiterGCHandlePtr).Target;
|
||||
|
||||
if (awaiter == null)
|
||||
{
|
||||
*outAwaiterIsNull = true.ToGodotBool();
|
||||
return;
|
||||
}
|
||||
|
||||
public IAwaiter<object[]> GetAwaiter()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
*outAwaiterIsNull = false.ToGodotBool();
|
||||
|
||||
internal void SignalCallback(object[] args)
|
||||
{
|
||||
completed = true;
|
||||
result = args;
|
||||
awaiter._completed = true;
|
||||
|
||||
if (action != null)
|
||||
object[] signalArgs = new object[argCount];
|
||||
|
||||
for (int i = 0; i < argCount; i++)
|
||||
signalArgs[i] = Marshaling.variant_to_mono_object(args[i]);
|
||||
|
||||
awaiter._result = signalArgs;
|
||||
|
||||
if (awaiter._action != null)
|
||||
{
|
||||
action();
|
||||
awaiter._action();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ExceptionUtils.DebugPrintUnhandledException(e);
|
||||
*outAwaiterIsNull = false.ToGodotBool();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ using System.Runtime.CompilerServices;
|
|||
using System.Security;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Godot.NativeInterop;
|
||||
|
||||
namespace Godot
|
||||
{
|
||||
|
@ -157,6 +158,7 @@ namespace Godot
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (from == 0 && to == len)
|
||||
{
|
||||
str = instance;
|
||||
|
@ -192,7 +194,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 +217,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");
|
||||
|
@ -355,7 +357,8 @@ namespace Godot
|
|||
/// <returns>The starting position of the substring, or -1 if not found.</returns>
|
||||
public static int Find(this string instance, string what, int from = 0, bool caseSensitive = true)
|
||||
{
|
||||
return instance.IndexOf(what, from, caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
|
||||
return instance.IndexOf(what, from,
|
||||
caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -366,7 +369,8 @@ namespace Godot
|
|||
{
|
||||
// TODO: Could be more efficient if we get a char version of `IndexOf`.
|
||||
// See https://github.com/dotnet/runtime/issues/44116
|
||||
return instance.IndexOf(what.ToString(), from, caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
|
||||
return instance.IndexOf(what.ToString(), from,
|
||||
caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>Find the last occurrence of a substring.</summary>
|
||||
|
@ -380,7 +384,8 @@ namespace Godot
|
|||
/// <returns>The starting position of the substring, or -1 if not found.</returns>
|
||||
public static int FindLast(this string instance, string what, int from, bool caseSensitive = true)
|
||||
{
|
||||
return instance.LastIndexOf(what, from, caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
|
||||
return instance.LastIndexOf(what, from,
|
||||
caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -623,6 +628,7 @@ namespace Godot
|
|||
{
|
||||
match = instance[source] == text[target];
|
||||
}
|
||||
|
||||
if (match)
|
||||
{
|
||||
source++;
|
||||
|
@ -732,7 +738,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");
|
||||
|
@ -808,15 +814,18 @@ namespace Godot
|
|||
switch (expr[0])
|
||||
{
|
||||
case '*':
|
||||
return ExprMatch(instance, expr.Substring(1), caseSensitive) || (instance.Length > 0 && ExprMatch(instance.Substring(1), expr, caseSensitive));
|
||||
return ExprMatch(instance, expr.Substring(1), caseSensitive) || (instance.Length > 0 &&
|
||||
ExprMatch(instance.Substring(1), expr, caseSensitive));
|
||||
case '?':
|
||||
return instance.Length > 0 && instance[0] != '.' && ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive);
|
||||
return instance.Length > 0 && instance[0] != '.' &&
|
||||
ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive);
|
||||
default:
|
||||
if (instance.Length == 0)
|
||||
return false;
|
||||
if (caseSensitive)
|
||||
return instance[0] == expr[0];
|
||||
return (char.ToUpper(instance[0]) == char.ToUpper(expr[0])) && ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive);
|
||||
return (char.ToUpper(instance[0]) == char.ToUpper(expr[0])) &&
|
||||
ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -847,25 +856,25 @@ namespace Godot
|
|||
/// <summary>
|
||||
/// Return the MD5 hash of the string as an array of bytes.
|
||||
/// </summary>
|
||||
public static byte[] MD5Buffer(this string instance)
|
||||
public static unsafe byte[] MD5Buffer(this string instance)
|
||||
{
|
||||
return godot_icall_String_md5_buffer(instance);
|
||||
using godot_string instanceStr = Marshaling.mono_string_to_godot(instance);
|
||||
using godot_packed_byte_array md5Buffer = default;
|
||||
NativeFuncs.godotsharp_string_md5_buffer(&instanceStr, &md5Buffer);
|
||||
return Marshaling.PackedByteArray_to_mono_array(&md5Buffer);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static byte[] godot_icall_String_md5_buffer(string str);
|
||||
|
||||
/// <summary>
|
||||
/// Return the MD5 hash of the string as a string.
|
||||
/// </summary>
|
||||
public static string MD5Text(this string instance)
|
||||
public static unsafe string MD5Text(this string instance)
|
||||
{
|
||||
return godot_icall_String_md5_text(instance);
|
||||
using godot_string instanceStr = Marshaling.mono_string_to_godot(instance);
|
||||
using godot_string md5Text = default;
|
||||
NativeFuncs.godotsharp_string_md5_text(&instanceStr, &md5Text);
|
||||
return Marshaling.mono_string_from_godot(md5Text);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static string godot_icall_String_md5_text(string str);
|
||||
|
||||
/// <summary>
|
||||
/// Perform a case-insensitive comparison to another string, return -1 if less, 0 if equal and +1 if greater.
|
||||
/// </summary>
|
||||
|
@ -981,26 +990,24 @@ namespace Godot
|
|||
/// <summary>
|
||||
/// Perform a search for a substring, but start from the end of the string instead of the beginning.
|
||||
/// </summary>
|
||||
public static int RFind(this string instance, string what, int from = -1)
|
||||
public static unsafe int RFind(this string instance, string what, int from = -1)
|
||||
{
|
||||
return godot_icall_String_rfind(instance, what, from);
|
||||
using godot_string instanceStr = Marshaling.mono_string_to_godot(instance);
|
||||
using godot_string whatStr = Marshaling.mono_string_to_godot(instance);
|
||||
return NativeFuncs.godotsharp_string_rfind(&instanceStr, &whatStr, from);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static int godot_icall_String_rfind(string str, string what, int from);
|
||||
|
||||
/// <summary>
|
||||
/// Perform a search for a substring, but start from the end of the string instead of the beginning.
|
||||
/// Also search case-insensitive.
|
||||
/// </summary>
|
||||
public static int RFindN(this string instance, string what, int from = -1)
|
||||
public static unsafe int RFindN(this string instance, string what, int from = -1)
|
||||
{
|
||||
return godot_icall_String_rfindn(instance, what, from);
|
||||
using godot_string instanceStr = Marshaling.mono_string_to_godot(instance);
|
||||
using godot_string whatStr = Marshaling.mono_string_to_godot(instance);
|
||||
return NativeFuncs.godotsharp_string_rfindn(&instanceStr, &whatStr, from);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static int godot_icall_String_rfindn(string str, string what, int from);
|
||||
|
||||
/// <summary>
|
||||
/// Return the right side of the string from a given position.
|
||||
/// </summary>
|
||||
|
@ -1042,25 +1049,25 @@ namespace Godot
|
|||
return instance.Substr(0, end + 1);
|
||||
}
|
||||
|
||||
public static byte[] SHA256Buffer(this string instance)
|
||||
public static unsafe byte[] SHA256Buffer(this string instance)
|
||||
{
|
||||
return godot_icall_String_sha256_buffer(instance);
|
||||
using godot_string instanceStr = Marshaling.mono_string_to_godot(instance);
|
||||
using godot_packed_byte_array sha256Buffer = default;
|
||||
NativeFuncs.godotsharp_string_sha256_buffer(&instanceStr, &sha256Buffer);
|
||||
return Marshaling.PackedByteArray_to_mono_array(&sha256Buffer);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static byte[] godot_icall_String_sha256_buffer(string str);
|
||||
|
||||
/// <summary>
|
||||
/// Return the SHA-256 hash of the string as a string.
|
||||
/// </summary>
|
||||
public static string SHA256Text(this string instance)
|
||||
public static unsafe string SHA256Text(this string instance)
|
||||
{
|
||||
return godot_icall_String_sha256_text(instance);
|
||||
using godot_string instanceStr = Marshaling.mono_string_to_godot(instance);
|
||||
using godot_string sha256Text = default;
|
||||
NativeFuncs.godotsharp_string_sha256_text(&instanceStr, &sha256Text);
|
||||
return Marshaling.mono_string_from_godot(sha256Text);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
internal extern static string godot_icall_String_sha256_text(string str);
|
||||
|
||||
/// <summary>
|
||||
/// Return the similarity index of the text compared to this string.
|
||||
/// 1 means totally similar and 0 means totally dissimilar.
|
||||
|
@ -1072,6 +1079,7 @@ namespace Godot
|
|||
// Equal strings are totally similar
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
if (instance.Length < 2 || text.Length < 2)
|
||||
{
|
||||
// No way to calculate similarity without a single bigram
|
||||
|
@ -1108,7 +1116,8 @@ namespace Godot
|
|||
/// </summary>
|
||||
public static string[] Split(this string instance, string divisor, bool allowEmpty = true)
|
||||
{
|
||||
return instance.Split(new[] { divisor }, allowEmpty ? StringSplitOptions.None : StringSplitOptions.RemoveEmptyEntries);
|
||||
return instance.Split(new[] { divisor },
|
||||
allowEmpty ? StringSplitOptions.None : StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1137,7 +1146,8 @@ namespace Godot
|
|||
return ret.ToArray();
|
||||
}
|
||||
|
||||
private static readonly char[] _nonPrintable = {
|
||||
private static readonly char[] _nonPrintable =
|
||||
{
|
||||
(char)00, (char)01, (char)02, (char)03, (char)04, (char)05,
|
||||
(char)06, (char)07, (char)08, (char)09, (char)10, (char)11,
|
||||
(char)12, (char)13, (char)14, (char)15, (char)16, (char)17,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
public 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,22 @@
|
|||
<OutputPath>bin/$(Configuration)</OutputPath>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<RootNamespace>Godot</RootNamespace>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<TargetFramework>net5.0</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" />
|
||||
|
@ -23,6 +32,10 @@
|
|||
<Compile Include="Core\Attributes\SignalAttribute.cs" />
|
||||
<Compile Include="Core\Attributes\ToolAttribute.cs" />
|
||||
<Compile Include="Core\Basis.cs" />
|
||||
<Compile Include="Core\Bridge\CSharpInstanceBridge.cs" />
|
||||
<Compile Include="Core\Bridge\GCHandleBridge.cs" />
|
||||
<Compile Include="Core\Bridge\ManagedCallbacks.cs" />
|
||||
<Compile Include="Core\Bridge\ScriptManagerBridge.cs" />
|
||||
<Compile Include="Core\Callable.cs" />
|
||||
<Compile Include="Core\Color.cs" />
|
||||
<Compile Include="Core\Colors.cs" />
|
||||
|
@ -30,7 +43,6 @@
|
|||
<Compile Include="Core\DelegateUtils.cs" />
|
||||
<Compile Include="Core\Dictionary.cs" />
|
||||
<Compile Include="Core\Dispatcher.cs" />
|
||||
<Compile Include="Core\DynamicObject.cs" />
|
||||
<Compile Include="Core\Extensions\NodeExtensions.cs" />
|
||||
<Compile Include="Core\Extensions\ObjectExtensions.cs" />
|
||||
<Compile Include="Core\Extensions\PackedSceneExtensions.cs" />
|
||||
|
@ -44,16 +56,24 @@
|
|||
<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\ExceptionUtils.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>
|
|
@ -1,3 +1,4 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("GodotSharpEditor")]
|
||||
[assembly: InternalsVisibleTo("GodotPlugins")]
|
||||
|
|
|
@ -4,9 +4,11 @@
|
|||
<OutputPath>bin/$(Configuration)</OutputPath>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<RootNamespace>Godot</RootNamespace>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<TargetFramework>net5.0</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>
|
|
@ -1,67 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* arguments_vector.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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef ARGUMENTS_VECTOR_H
|
||||
#define ARGUMENTS_VECTOR_H
|
||||
|
||||
#include "core/os/memory.h"
|
||||
|
||||
template <typename T, int POOL_SIZE = 5>
|
||||
struct ArgumentsVector {
|
||||
private:
|
||||
T pool[POOL_SIZE];
|
||||
T *_ptr;
|
||||
int size;
|
||||
|
||||
ArgumentsVector() = delete;
|
||||
ArgumentsVector(const ArgumentsVector &) = delete;
|
||||
|
||||
public:
|
||||
T *ptr() { return _ptr; }
|
||||
T &get(int p_idx) { return _ptr[p_idx]; }
|
||||
void set(int p_idx, const T &p_value) { _ptr[p_idx] = p_value; }
|
||||
|
||||
explicit ArgumentsVector(int p_size) :
|
||||
size(p_size) {
|
||||
if (p_size <= POOL_SIZE) {
|
||||
_ptr = pool;
|
||||
} else {
|
||||
_ptr = memnew_arr(T, p_size);
|
||||
}
|
||||
}
|
||||
|
||||
~ArgumentsVector() {
|
||||
if (size > POOL_SIZE) {
|
||||
memdelete_arr(_ptr);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // ARGUMENTS_VECTOR_H
|
|
@ -1,257 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* base_object_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/object/class_db.h"
|
||||
#include "core/object/ref_counted.h"
|
||||
#include "core/string/string_name.h"
|
||||
|
||||
#include "../csharp_script.h"
|
||||
#include "../mono_gd/gd_mono_cache.h"
|
||||
#include "../mono_gd/gd_mono_class.h"
|
||||
#include "../mono_gd/gd_mono_internals.h"
|
||||
#include "../mono_gd/gd_mono_marshal.h"
|
||||
#include "../mono_gd/gd_mono_utils.h"
|
||||
#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);
|
||||
#endif
|
||||
|
||||
if (p_ptr->get_script_instance()) {
|
||||
CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(p_ptr->get_script_instance());
|
||||
if (cs_instance) {
|
||||
if (!cs_instance->is_destructing_script_instance()) {
|
||||
cs_instance->mono_object_disposed(p_obj);
|
||||
p_ptr->set_script_instance(nullptr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void *data = CSharpLanguage::get_existing_instance_binding(p_ptr);
|
||||
|
||||
if (data) {
|
||||
CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
|
||||
if (script_binding.inited) {
|
||||
MonoGCHandleData &gchandle = script_binding.gchandle;
|
||||
if (!gchandle.is_released()) {
|
||||
CSharpLanguage::release_script_gchandle(p_obj, gchandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void godot_icall_RefCounted_Disposed(MonoObject *p_obj, Object *p_ptr, MonoBoolean p_is_finalizer) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
CRASH_COND(p_ptr == nullptr);
|
||||
// This is only called with RefCounted derived classes
|
||||
CRASH_COND(!Object::cast_to<RefCounted>(p_ptr));
|
||||
#endif
|
||||
|
||||
RefCounted *rc = static_cast<RefCounted *>(p_ptr);
|
||||
|
||||
if (rc->get_script_instance()) {
|
||||
CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(rc->get_script_instance());
|
||||
if (cs_instance) {
|
||||
if (!cs_instance->is_destructing_script_instance()) {
|
||||
bool delete_owner;
|
||||
bool remove_script_instance;
|
||||
|
||||
cs_instance->mono_object_disposed_baseref(p_obj, p_is_finalizer, delete_owner, remove_script_instance);
|
||||
|
||||
if (delete_owner) {
|
||||
memdelete(rc);
|
||||
} else if (remove_script_instance) {
|
||||
rc->set_script_instance(nullptr);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Unsafe refcount decrement. The managed instance also counts as a reference.
|
||||
// See: CSharpLanguage::alloc_instance_binding_data(Object *p_object)
|
||||
CSharpLanguage::get_singleton()->pre_unsafe_unreference(rc);
|
||||
if (rc->unreference()) {
|
||||
memdelete(rc);
|
||||
} else {
|
||||
void *data = CSharpLanguage::get_existing_instance_binding(rc);
|
||||
|
||||
if (data) {
|
||||
CSharpScriptBinding &script_binding = ((Map<Object *, CSharpScriptBinding>::Element *)data)->get();
|
||||
if (script_binding.inited) {
|
||||
MonoGCHandleData &gchandle = script_binding.gchandle;
|
||||
if (!gchandle.is_released()) {
|
||||
CSharpLanguage::release_script_gchandle(p_obj, gchandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void godot_icall_Object_ConnectEventSignals(Object *p_ptr) {
|
||||
CSharpInstance *csharp_instance = CAST_CSHARP_INSTANCE(p_ptr->get_script_instance());
|
||||
if (csharp_instance) {
|
||||
csharp_instance->connect_event_signals();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Ref<WeakRef> wref;
|
||||
RefCounted *rc = Object::cast_to<RefCounted>(p_ptr);
|
||||
|
||||
if (rc) {
|
||||
REF r = rc;
|
||||
if (!r.is_valid()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wref.instantiate();
|
||||
wref->set_ref(r);
|
||||
} else {
|
||||
wref.instantiate();
|
||||
wref->set_obj(p_ptr);
|
||||
}
|
||||
|
||||
return GDMonoUtils::unmanaged_get_managed(wref.ptr());
|
||||
}
|
||||
|
||||
int32_t godot_icall_SignalAwaiter_connect(Object *p_source, StringName *p_signal, Object *p_target, MonoObject *p_awaiter) {
|
||||
StringName signal = p_signal ? *p_signal : StringName();
|
||||
return (int32_t)gd_mono_connect_signal_awaiter(p_source, signal, p_target, p_awaiter);
|
||||
}
|
||||
|
||||
MonoArray *godot_icall_DynamicGodotObject_SetMemberList(Object *p_ptr) {
|
||||
List<PropertyInfo> property_list;
|
||||
p_ptr->get_property_list(&property_list);
|
||||
|
||||
MonoArray *result = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(String), property_list.size());
|
||||
|
||||
int i = 0;
|
||||
for (const PropertyInfo &E : property_list) {
|
||||
MonoString *boxed = GDMonoMarshal::mono_string_from_godot(E.name);
|
||||
mono_array_setref(result, i, boxed);
|
||||
i++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
MonoBoolean godot_icall_DynamicGodotObject_InvokeMember(Object *p_ptr, MonoString *p_name, MonoArray *p_args, MonoObject **r_result) {
|
||||
String name = GDMonoMarshal::mono_string_to_godot(p_name);
|
||||
|
||||
int argc = mono_array_length(p_args);
|
||||
|
||||
ArgumentsVector<Variant> arg_store(argc);
|
||||
ArgumentsVector<const Variant *> args(argc);
|
||||
|
||||
for (int i = 0; i < argc; i++) {
|
||||
MonoObject *elem = mono_array_get(p_args, MonoObject *, i);
|
||||
arg_store.set(i, GDMonoMarshal::mono_object_to_variant(elem));
|
||||
args.set(i, &arg_store.get(i));
|
||||
}
|
||||
|
||||
Callable::CallError error;
|
||||
Variant result = p_ptr->call(StringName(name), args.ptr(), argc, error);
|
||||
|
||||
*r_result = GDMonoMarshal::variant_to_mono_object(result);
|
||||
|
||||
return error.error == Callable::CallError::CALL_OK;
|
||||
}
|
||||
|
||||
MonoBoolean godot_icall_DynamicGodotObject_GetMember(Object *p_ptr, MonoString *p_name, MonoObject **r_result) {
|
||||
String name = GDMonoMarshal::mono_string_to_godot(p_name);
|
||||
|
||||
bool valid;
|
||||
Variant value = p_ptr->get(StringName(name), &valid);
|
||||
|
||||
if (valid) {
|
||||
*r_result = GDMonoMarshal::variant_to_mono_object(value);
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
MonoBoolean godot_icall_DynamicGodotObject_SetMember(Object *p_ptr, MonoString *p_name, MonoObject *p_value) {
|
||||
String name = GDMonoMarshal::mono_string_to_godot(p_name);
|
||||
Variant value = GDMonoMarshal::mono_object_to_variant(p_value);
|
||||
|
||||
bool valid;
|
||||
p_ptr->set(StringName(name), value, &valid);
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
MonoString *godot_icall_Object_ToString(Object *p_ptr) {
|
||||
#ifdef DEBUG_ENABLED
|
||||
// Cannot happen in C#; would get an ObjectDisposedException instead.
|
||||
CRASH_COND(p_ptr == nullptr);
|
||||
#endif
|
||||
// Can't call 'Object::to_string()' here, as that can end up calling 'ToString' again resulting in an endless circular loop.
|
||||
String result = "[" + p_ptr->get_class() + ":" + itos(p_ptr->get_instance_id()) + "]";
|
||||
return GDMonoMarshal::mono_string_from_godot(result);
|
||||
}
|
||||
|
||||
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);
|
||||
GDMonoUtils::add_internal_call("Godot.DynamicGodotObject::godot_icall_DynamicGodotObject_SetMemberList", godot_icall_DynamicGodotObject_SetMemberList);
|
||||
GDMonoUtils::add_internal_call("Godot.DynamicGodotObject::godot_icall_DynamicGodotObject_InvokeMember", godot_icall_DynamicGodotObject_InvokeMember);
|
||||
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
|
|
@ -1,369 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* collections_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 <mono/metadata/exception.h>
|
||||
|
||||
#include "core/variant/array.h"
|
||||
|
||||
#include "../mono_gd/gd_mono_cache.h"
|
||||
#include "../mono_gd/gd_mono_class.h"
|
||||
#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_Dtor(Array *ptr) {
|
||||
memdelete(ptr);
|
||||
}
|
||||
|
||||
MonoObject *godot_icall_Array_At(Array *ptr, int32_t index) {
|
||||
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));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void godot_icall_Array_SetAt(Array *ptr, int32_t index, MonoObject *value) {
|
||||
if (index < 0 || index >= ptr->size()) {
|
||||
GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range());
|
||||
return;
|
||||
}
|
||||
ptr->operator[](index) = GDMonoMarshal::mono_object_to_variant(value);
|
||||
}
|
||||
|
||||
int32_t godot_icall_Array_Count(Array *ptr) {
|
||||
return ptr->size();
|
||||
}
|
||||
|
||||
int32_t godot_icall_Array_Add(Array *ptr, MonoObject *item) {
|
||||
ptr->append(GDMonoMarshal::mono_object_to_variant(item));
|
||||
return ptr->size();
|
||||
}
|
||||
|
||||
void godot_icall_Array_Clear(Array *ptr) {
|
||||
ptr->clear();
|
||||
}
|
||||
|
||||
MonoBoolean godot_icall_Array_Contains(Array *ptr, MonoObject *item) {
|
||||
return ptr->find(GDMonoMarshal::mono_object_to_variant(item)) != -1;
|
||||
}
|
||||
|
||||
void godot_icall_Array_CopyTo(Array *ptr, MonoArray *array, int32_t array_index) {
|
||||
unsigned int count = ptr->size();
|
||||
|
||||
if (mono_array_length(array) < (array_index + count)) {
|
||||
MonoException *exc = mono_get_exception_argument("", "Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
|
||||
GDMonoUtils::set_pending_exception(exc);
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
MonoObject *boxed = GDMonoMarshal::variant_to_mono_object(ptr->operator[](i));
|
||||
mono_array_setref(array, array_index, boxed);
|
||||
array_index++;
|
||||
}
|
||||
}
|
||||
|
||||
Array *godot_icall_Array_Ctor_MonoArray(MonoArray *mono_array) {
|
||||
Array *godot_array = memnew(Array);
|
||||
unsigned int count = mono_array_length(mono_array);
|
||||
godot_array->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);
|
||||
}
|
||||
return godot_array;
|
||||
}
|
||||
|
||||
Array *godot_icall_Array_Duplicate(Array *ptr, MonoBoolean deep) {
|
||||
return memnew(Array(ptr->duplicate(deep)));
|
||||
}
|
||||
|
||||
Array *godot_icall_Array_Concatenate(Array *left, Array *right) {
|
||||
int count = left->size() + right->size();
|
||||
Array *new_array = memnew(Array(left->duplicate(false)));
|
||||
new_array->resize(count);
|
||||
for (unsigned int i = 0; i < (unsigned int)right->size(); i++) {
|
||||
new_array->operator[](i + left->size()) = right->operator[](i);
|
||||
}
|
||||
return new_array;
|
||||
}
|
||||
|
||||
int32_t godot_icall_Array_IndexOf(Array *ptr, MonoObject *item) {
|
||||
return ptr->find(GDMonoMarshal::mono_object_to_variant(item));
|
||||
}
|
||||
|
||||
void godot_icall_Array_Insert(Array *ptr, int32_t index, MonoObject *item) {
|
||||
if (index < 0 || index > ptr->size()) {
|
||||
GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range());
|
||||
return;
|
||||
}
|
||||
ptr->insert(index, GDMonoMarshal::mono_object_to_variant(item));
|
||||
}
|
||||
|
||||
MonoBoolean godot_icall_Array_Remove(Array *ptr, MonoObject *item) {
|
||||
int idx = ptr->find(GDMonoMarshal::mono_object_to_variant(item));
|
||||
if (idx >= 0) {
|
||||
ptr->remove(idx);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void godot_icall_Array_RemoveAt(Array *ptr, int32_t index) {
|
||||
if (index < 0 || index >= ptr->size()) {
|
||||
GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range());
|
||||
return;
|
||||
}
|
||||
ptr->remove(index);
|
||||
}
|
||||
|
||||
int32_t godot_icall_Array_Resize(Array *ptr, int32_t new_size) {
|
||||
return (int32_t)ptr->resize(new_size);
|
||||
}
|
||||
|
||||
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_Dtor(Dictionary *ptr) {
|
||||
memdelete(ptr);
|
||||
}
|
||||
|
||||
MonoObject *godot_icall_Dictionary_GetValue(Dictionary *ptr, MonoObject *key) {
|
||||
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);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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()));
|
||||
}
|
||||
|
||||
Array *godot_icall_Dictionary_Values(Dictionary *ptr) {
|
||||
return memnew(Array(ptr->values()));
|
||||
}
|
||||
|
||||
int32_t godot_icall_Dictionary_Count(Dictionary *ptr) {
|
||||
return ptr->size();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void godot_icall_Dictionary_Add(Dictionary *ptr, MonoObject *key, MonoObject *value) {
|
||||
Variant varKey = GDMonoMarshal::mono_object_to_variant(key);
|
||||
Variant *ret = ptr->getptr(varKey);
|
||||
if (ret != nullptr) {
|
||||
GDMonoUtils::set_pending_exception(mono_get_exception_argument("key", "An element with the same key already exists"));
|
||||
return;
|
||||
}
|
||||
ptr->operator[](varKey) = GDMonoMarshal::mono_object_to_variant(value);
|
||||
}
|
||||
|
||||
void godot_icall_Dictionary_Clear(Dictionary *ptr) {
|
||||
ptr->clear();
|
||||
}
|
||||
|
||||
MonoBoolean godot_icall_Dictionary_Contains(Dictionary *ptr, MonoObject *key, MonoObject *value) {
|
||||
// no dupes
|
||||
Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
|
||||
return ret != nullptr && *ret == GDMonoMarshal::mono_object_to_variant(value);
|
||||
}
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
MonoBoolean godot_icall_Dictionary_RemoveKey(Dictionary *ptr, MonoObject *key) {
|
||||
return ptr->erase(GDMonoMarshal::mono_object_to_variant(key));
|
||||
}
|
||||
|
||||
MonoBoolean godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, MonoObject *value) {
|
||||
Variant varKey = GDMonoMarshal::mono_object_to_variant(key);
|
||||
|
||||
// no dupes
|
||||
Variant *ret = ptr->getptr(varKey);
|
||||
if (ret != nullptr && *ret == GDMonoMarshal::mono_object_to_variant(value)) {
|
||||
ptr->erase(varKey);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
MonoBoolean godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoObject **value) {
|
||||
Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
|
||||
if (ret == nullptr) {
|
||||
*value = nullptr;
|
||||
return false;
|
||||
}
|
||||
*value = GDMonoMarshal::variant_to_mono_object(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());
|
||||
}
|
||||
|
||||
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);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Clear", godot_icall_Array_Clear);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Concatenate", godot_icall_Array_Concatenate);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Contains", godot_icall_Array_Contains);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_CopyTo", godot_icall_Array_CopyTo);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Duplicate", godot_icall_Array_Duplicate);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_IndexOf", godot_icall_Array_IndexOf);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Insert", godot_icall_Array_Insert);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Array::godot_icall_Array_Remove", godot_icall_Array_Remove);
|
||||
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);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Count", godot_icall_Dictionary_Count);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_KeyValuePairs", godot_icall_Dictionary_KeyValuePairs);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_KeyValuePairAt", godot_icall_Dictionary_KeyValuePairAt);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Add", godot_icall_Dictionary_Add);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Clear", godot_icall_Dictionary_Clear);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Contains", godot_icall_Dictionary_Contains);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_ContainsKey", godot_icall_Dictionary_ContainsKey);
|
||||
GDMonoUtils::add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Duplicate", godot_icall_Dictionary_Duplicate);
|
||||
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
|
|
@ -1,321 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* gd_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/io/marshalls.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/string/ustring.h"
|
||||
#include "core/variant/array.h"
|
||||
#include "core/variant/variant.h"
|
||||
#include "core/variant/variant_parser.h"
|
||||
|
||||
#include "../mono_gd/gd_mono_cache.h"
|
||||
#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) {
|
||||
Variant ret;
|
||||
PackedByteArray varr = GDMonoMarshal::mono_array_to_PackedByteArray(p_bytes);
|
||||
Error err = decode_variant(ret, varr.ptr(), varr.size(), nullptr, p_allow_objects);
|
||||
if (err != OK) {
|
||||
ret = RTR("Not enough bytes for decoding bytes, or invalid format.");
|
||||
}
|
||||
return GDMonoMarshal::variant_to_mono_object(ret);
|
||||
}
|
||||
|
||||
MonoObject *godot_icall_GD_convert(MonoObject *p_what, int32_t p_type) {
|
||||
Variant what = GDMonoMarshal::mono_object_to_variant(p_what);
|
||||
const Variant *args[1] = { &what };
|
||||
Callable::CallError ce;
|
||||
Variant ret;
|
||||
Variant::construct(Variant::Type(p_type), ret, args, 1, ce);
|
||||
ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, nullptr);
|
||||
return GDMonoMarshal::variant_to_mono_object(ret);
|
||||
}
|
||||
|
||||
int godot_icall_GD_hash(MonoObject *p_var) {
|
||||
return GDMonoMarshal::mono_object_to_variant(p_var).hash();
|
||||
}
|
||||
|
||||
MonoObject *godot_icall_GD_instance_from_id(uint64_t p_instance_id) {
|
||||
return GDMonoUtils::unmanaged_get_managed(ObjectDB::get_instance(ObjectID(p_instance_id)));
|
||||
}
|
||||
|
||||
void godot_icall_GD_print(MonoArray *p_what) {
|
||||
String str;
|
||||
int length = mono_array_length(p_what);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
|
||||
|
||||
MonoException *exc = nullptr;
|
||||
String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
|
||||
|
||||
if (exc) {
|
||||
GDMonoUtils::set_pending_exception(exc);
|
||||
return;
|
||||
}
|
||||
|
||||
str += elem_str;
|
||||
}
|
||||
|
||||
print_line(str);
|
||||
}
|
||||
|
||||
void godot_icall_GD_printerr(MonoArray *p_what) {
|
||||
String str;
|
||||
int length = mono_array_length(p_what);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
|
||||
|
||||
MonoException *exc = nullptr;
|
||||
String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
|
||||
|
||||
if (exc) {
|
||||
GDMonoUtils::set_pending_exception(exc);
|
||||
return;
|
||||
}
|
||||
|
||||
str += elem_str;
|
||||
}
|
||||
|
||||
print_error(str);
|
||||
}
|
||||
|
||||
void godot_icall_GD_printraw(MonoArray *p_what) {
|
||||
String str;
|
||||
int length = mono_array_length(p_what);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
|
||||
|
||||
MonoException *exc = nullptr;
|
||||
String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
|
||||
|
||||
if (exc) {
|
||||
GDMonoUtils::set_pending_exception(exc);
|
||||
return;
|
||||
}
|
||||
|
||||
str += elem_str;
|
||||
}
|
||||
|
||||
OS::get_singleton()->print("%s", str.utf8().get_data());
|
||||
}
|
||||
|
||||
void godot_icall_GD_prints(MonoArray *p_what) {
|
||||
String str;
|
||||
int length = mono_array_length(p_what);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
|
||||
|
||||
MonoException *exc = nullptr;
|
||||
String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
|
||||
|
||||
if (exc) {
|
||||
GDMonoUtils::set_pending_exception(exc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (i) {
|
||||
str += " ";
|
||||
}
|
||||
|
||||
str += elem_str;
|
||||
}
|
||||
|
||||
print_line(str);
|
||||
}
|
||||
|
||||
void godot_icall_GD_printt(MonoArray *p_what) {
|
||||
String str;
|
||||
int length = mono_array_length(p_what);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
|
||||
|
||||
MonoException *exc = nullptr;
|
||||
String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
|
||||
|
||||
if (exc) {
|
||||
GDMonoUtils::set_pending_exception(exc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (i) {
|
||||
str += "\t";
|
||||
}
|
||||
|
||||
str += elem_str;
|
||||
}
|
||||
|
||||
print_line(str);
|
||||
}
|
||||
|
||||
float godot_icall_GD_randf() {
|
||||
return Math::randf();
|
||||
}
|
||||
|
||||
uint32_t godot_icall_GD_randi() {
|
||||
return Math::rand();
|
||||
}
|
||||
|
||||
void godot_icall_GD_randomize() {
|
||||
Math::randomize();
|
||||
}
|
||||
|
||||
double godot_icall_GD_randf_range(double from, double to) {
|
||||
return Math::random(from, to);
|
||||
}
|
||||
|
||||
int32_t godot_icall_GD_randi_range(int32_t from, int32_t to) {
|
||||
return Math::random(from, to);
|
||||
}
|
||||
|
||||
uint32_t godot_icall_GD_rand_seed(uint64_t seed, uint64_t *newSeed) {
|
||||
uint32_t ret = Math::rand_from_seed(&seed);
|
||||
*newSeed = seed;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void godot_icall_GD_seed(uint64_t p_seed) {
|
||||
Math::seed(p_seed);
|
||||
}
|
||||
|
||||
MonoString *godot_icall_GD_str(MonoArray *p_what) {
|
||||
String str;
|
||||
Array what = GDMonoMarshal::mono_array_to_Array(p_what);
|
||||
|
||||
for (int i = 0; i < what.size(); i++) {
|
||||
String os = what[i].operator String();
|
||||
|
||||
if (i == 0) {
|
||||
str = os;
|
||||
} else {
|
||||
str += os;
|
||||
}
|
||||
}
|
||||
|
||||
return GDMonoMarshal::mono_string_from_godot(str);
|
||||
}
|
||||
|
||||
MonoObject *godot_icall_GD_str2var(MonoString *p_str) {
|
||||
Variant ret;
|
||||
|
||||
VariantParser::StreamString ss;
|
||||
ss.s = GDMonoMarshal::mono_string_to_godot(p_str);
|
||||
|
||||
String errs;
|
||||
int line;
|
||||
Error err = VariantParser::parse(&ss, ret, errs, line);
|
||||
if (err != OK) {
|
||||
String err_str = "Parse error at line " + itos(line) + ": " + errs + ".";
|
||||
ERR_PRINT(err_str);
|
||||
ret = err_str;
|
||||
}
|
||||
|
||||
return GDMonoMarshal::variant_to_mono_object(ret);
|
||||
}
|
||||
|
||||
MonoBoolean godot_icall_GD_type_exists(StringName *p_type) {
|
||||
StringName type = p_type ? *p_type : StringName();
|
||||
return ClassDB::class_exists(type);
|
||||
}
|
||||
|
||||
void godot_icall_GD_pusherror(MonoString *p_str) {
|
||||
ERR_PRINT(GDMonoMarshal::mono_string_to_godot(p_str));
|
||||
}
|
||||
|
||||
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) {
|
||||
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).");
|
||||
|
||||
barr.resize(len);
|
||||
encode_variant(var, barr.ptrw(), len, p_full_objects);
|
||||
|
||||
return GDMonoMarshal::PackedByteArray_to_mono_array(barr);
|
||||
}
|
||||
|
||||
MonoString *godot_icall_GD_var2str(MonoObject *p_var) {
|
||||
String vars;
|
||||
VariantWriter::write_to_string(GDMonoMarshal::mono_object_to_variant(p_var), vars);
|
||||
return GDMonoMarshal::mono_string_from_godot(vars);
|
||||
}
|
||||
|
||||
uint32_t godot_icall_TypeToVariantType(MonoReflectionType *p_refl_type) {
|
||||
return (uint32_t)GDMonoMarshal::managed_to_variant_type(ManagedType::from_reftype(p_refl_type));
|
||||
}
|
||||
|
||||
MonoObject *godot_icall_DefaultGodotTaskScheduler() {
|
||||
return GDMonoCache::cached_data.task_scheduler_handle->get_target();
|
||||
}
|
||||
|
||||
void godot_register_gd_icalls() {
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_bytes2var", godot_icall_GD_bytes2var);
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_convert", godot_icall_GD_convert);
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_hash", godot_icall_GD_hash);
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_instance_from_id", godot_icall_GD_instance_from_id);
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_pusherror", godot_icall_GD_pusherror);
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_pushwarning", godot_icall_GD_pushwarning);
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_print", godot_icall_GD_print);
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_printerr", godot_icall_GD_printerr);
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_printraw", godot_icall_GD_printraw);
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_prints", godot_icall_GD_prints);
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_printt", godot_icall_GD_printt);
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randf", godot_icall_GD_randf);
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randi", godot_icall_GD_randi);
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randomize", godot_icall_GD_randomize);
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randf_range", godot_icall_GD_randf_range);
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_randi_range", godot_icall_GD_randi_range);
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_rand_seed", godot_icall_GD_rand_seed);
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_seed", godot_icall_GD_seed);
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_str", godot_icall_GD_str);
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_str2var", godot_icall_GD_str2var);
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_type_exists", godot_icall_GD_type_exists);
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_var2bytes", godot_icall_GD_var2bytes);
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_GD_var2str", godot_icall_GD_var2str);
|
||||
GDMonoUtils::add_internal_call("Godot.GD::godot_icall_TypeToVariantType", godot_icall_TypeToVariantType);
|
||||
|
||||
// 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,97 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* nodepath_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/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();
|
||||
}
|
||||
|
||||
int32_t godot_icall_NodePath_get_name_count(NodePath *p_ptr) {
|
||||
return p_ptr->get_name_count();
|
||||
}
|
||||
|
||||
MonoString *godot_icall_NodePath_get_name(NodePath *p_ptr, uint32_t p_idx) {
|
||||
return GDMonoMarshal::mono_string_from_godot(p_ptr->get_name(p_idx));
|
||||
}
|
||||
|
||||
int32_t godot_icall_NodePath_get_subname_count(NodePath *p_ptr) {
|
||||
return p_ptr->get_subname_count();
|
||||
}
|
||||
|
||||
MonoString *godot_icall_NodePath_get_subname(NodePath *p_ptr, uint32_t p_idx) {
|
||||
return GDMonoMarshal::mono_string_from_godot(p_ptr->get_subname(p_idx));
|
||||
}
|
||||
|
||||
MonoString *godot_icall_NodePath_get_concatenated_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()));
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
GDMonoUtils::add_internal_call("Godot.NodePath::godot_icall_NodePath_get_name_count", godot_icall_NodePath_get_name_count);
|
||||
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,64 +0,0 @@
|
|||
/*************************************************************************/
|
||||
/* rid_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/io/resource.h"
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/templates/rid.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);
|
||||
}
|
||||
|
||||
void godot_icall_RID_Dtor(RID *p_ptr) {
|
||||
ERR_FAIL_NULL(p_ptr);
|
||||
memdelete(p_ptr);
|
||||
}
|
||||
|
||||
uint32_t godot_icall_RID_get_id(RID *p_ptr) {
|
||||
return p_ptr->get_id();
|
||||
}
|
||||
|
||||
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
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue